Sat Mar 10 01:54:40 2012

Asterisk developer's documentation


app_voicemail_imapstorage.c File Reference

Comedian Mail - Voicemail System. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <time.h>
#include <dirent.h>
#include "asterisk/logger.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/module.h"
#include "asterisk/adsi.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/dsp.h"
#include "asterisk/localtime.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/stringfields.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj2.h"
#include "asterisk/event.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/test.h"

Go to the source code of this file.

Data Structures

struct  ast_vm_user
struct  baseio
struct  inprocess
struct  leave_vm_options
 Options for leaving voicemail with the voicemail() application. More...
struct  mwi_sub
 An MWI subscription. More...
struct  mwi_sub_task
struct  mwi_subs
struct  users
 list of users found in the config file More...
struct  vm_state
struct  vm_zone
struct  zones

Defines

#define ASTERISK_USERNAME   "asterisk"
#define BASELINELEN   72
#define BASEMAXINLINE   256
#define CHUNKSIZE   65536
#define COMMAND_TIMEOUT   5000
#define COPY(a, b, c, d, e, f, g, h)   (copy_plain_file(g,h));
#define DATA_EXPORT_VM_USERS(USER)
#define DATA_EXPORT_VM_ZONES(ZONE)
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"
#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"
#define DEFAULT_POLL_FREQ   30
#define DELETE(a, b, c, d)   (vm_delete(c))
#define DISPOSE(a, b)
#define ENDL   "\n"
#define ERROR_LOCK_PATH   -100
#define EXISTS(a, b, c, d)   (ast_fileexists(c,NULL,d) > 0)
#define HVSU_OUTPUT_FORMAT   "%-10s %-5s %-25s %-10s %6s\n"
#define HVSZ_OUTPUT_FORMAT   "%-15s %-20s %-45s\n"
#define INTRO   "vm-intro"
#define MAX_DATETIME_FORMAT   512
#define MAX_NUM_CID_CONTEXTS   10
#define MAXMSG   100
#define MAXMSGLIMIT   9999
#define MINPASSWORD   0
#define OPERATOR_EXIT   300
#define PWDCHANGE_EXTERNAL   (1 << 2)
#define PWDCHANGE_INTERNAL   (1 << 1)
#define RENAME(a, b, c, d, e, f, g, h)   (rename_file(g,h));
#define RETRIEVE(a, b, c, d)
#define SENDMAIL   "/usr/sbin/sendmail -t"
#define SMDI_MWI_WAIT_TIMEOUT   1000
#define STORE(a, b, c, d, e, f, g, h, i, j)
#define tdesc   "Comedian Mail (Voicemail System)"
#define VALID_DTMF   "1234567890*#"
#define VM_ALLOCED   (1 << 13)
#define VM_ATTACH   (1 << 11)
#define VM_DELETE   (1 << 12)
#define VM_DIRECFORWARD   (1 << 10)
#define VM_ENVELOPE   (1 << 4)
#define VM_FORCEGREET   (1 << 8)
#define VM_FORCENAME   (1 << 7)
#define VM_FWDURGAUTO   (1 << 18)
#define VM_MESSAGEWRAP   (1 << 17)
#define VM_MOVEHEARD   (1 << 16)
#define VM_OPERATOR   (1 << 1)
#define VM_PBXSKIP   (1 << 9)
#define VM_REVIEW   (1 << 0)
#define VM_SAYCID   (1 << 2)
#define VM_SAYDURATION   (1 << 5)
#define VM_SEARCH   (1 << 14)
#define VM_SKIPAFTERCMD   (1 << 6)
#define VM_SVMAIL   (1 << 3)
#define VM_TEMPGREETWARN   (1 << 15)
#define VMSTATE_MAX_MSG_ARRAY   256
#define VOICEMAIL_CONFIG   "voicemail.conf"
#define VOICEMAIL_DIR_MODE   0777
#define VOICEMAIL_FILE_MODE   0666

Enumerations

enum  vm_box {
  NEW_FOLDER, OLD_FOLDER, WORK_FOLDER, FAMILY_FOLDER,
  FRIENDS_FOLDER, GREETINGS_FOLDER
}
enum  vm_option_args { OPT_ARG_RECORDGAIN = 0, OPT_ARG_PLAYFOLDER = 1, OPT_ARG_DTMFEXIT = 2, OPT_ARG_ARRAY_SIZE = 3 }
enum  vm_option_flags {
  OPT_SILENT = (1 << 0), OPT_BUSY_GREETING = (1 << 1), OPT_UNAVAIL_GREETING = (1 << 2), OPT_RECORDGAIN = (1 << 3),
  OPT_PREPEND_MAILBOX = (1 << 4), OPT_AUTOPLAY = (1 << 6), OPT_DTMFEXIT = (1 << 7), OPT_MESSAGE_Urgent = (1 << 8),
  OPT_MESSAGE_PRIORITY = (1 << 9)
}
enum  vm_passwordlocation { OPT_PWLOC_VOICEMAILCONF = 0, OPT_PWLOC_SPOOLDIR = 1, OPT_PWLOC_USERSCONF = 2 }

Functions

static int __has_voicemail (const char *context, const char *mailbox, const char *folder, int shortcircuit)
static void __reg_module (void)
static void __unreg_module (void)
static int acf_mailbox_exists (struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static int actual_load_config (int reload, struct ast_config *cfg, struct ast_config *ucfg)
static int add_email_attachment (FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
static void adsi_begin (struct ast_channel *chan, int *useadsi)
static void adsi_delete (struct ast_channel *chan, struct vm_state *vms)
static void adsi_folders (struct ast_channel *chan, int start, char *label)
static void adsi_goodbye (struct ast_channel *chan)
static int adsi_load_vmail (struct ast_channel *chan, int *useadsi)
static void adsi_login (struct ast_channel *chan)
static int adsi_logo (unsigned char *buf)
static void adsi_message (struct ast_channel *chan, struct vm_state *vms)
static void adsi_password (struct ast_channel *chan)
static void adsi_status (struct ast_channel *chan, struct vm_state *vms)
static void adsi_status2 (struct ast_channel *chan, struct vm_state *vms)
static int advanced_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
 The advanced options within a message.
static int append_mailbox (const char *context, const char *box, const char *data)
static void apply_option (struct ast_vm_user *vmu, const char *var, const char *value)
 Sets a a specific property value.
static void apply_options (struct ast_vm_user *vmu, const char *options)
 Destructively Parse options and apply.
static void apply_options_full (struct ast_vm_user *retval, struct ast_variable *var)
 Loads the options specific to a voicemail user.
 AST_DATA_STRUCTURE (vm_zone, DATA_EXPORT_VM_ZONES)
 AST_DATA_STRUCTURE (ast_vm_user, DATA_EXPORT_VM_USERS)
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.
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.
 AST_TEST_DEFINE (test_voicemail_vmuser)
static int base_encode (char *filename, FILE *so)
 Performs a base 64 encode algorithm on the contents of a File.
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 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.
static int check_password (struct ast_vm_user *vmu, char *password)
 Check that password meets minimum required length.
static int close_mailbox (struct vm_state *vms, struct ast_vm_user *vmu)
static char * complete_voicemail_show_users (const char *line, const char *word, int pos, int state)
static int copy (char *infile, char *outfile)
 Utility function to copy a file.
static int copy_message (struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt, char *dir, const char *flag)
 Copies a message from one mailbox to another.
static void copy_plain_file (char *frompath, char *topath)
 Copies a voicemail information (envelope) file.
static int count_messages (struct ast_vm_user *vmu, char *dir)
 Find all .txt files - even if they are not in sequence from 0000.
static int create_dirpath (char *dest, int len, const char *context, const char *ext, const char *folder)
 basically mkdir -p $dest/$context/$ext/$folder
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.
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.
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.
static void free_user (struct ast_vm_user *vmu)
static void free_vm_users (void)
 Free the users structure.
static void free_vm_zones (void)
 Free the zones structure.
static void free_zone (struct vm_zone *z)
static int get_date (char *s, int len)
 Gets the current date and time, as formatted string.
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_folder2 (struct ast_channel *chan, char *fn, int start)
 plays a prompt and waits for a keypress.
static int get_folder_by_name (const char *name)
static int handle_subscribe (void *datap)
static int handle_unsubscribe (void *datap)
static char * handle_voicemail_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Reload voicemail configuration from the CLI.
static char * handle_voicemail_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail users in the CLI.
static char * handle_voicemail_show_zones (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show a list of voicemail zones in the CLI.
static int has_voicemail (const char *mailbox, const char *folder)
 Determines if the given folder has messages.
static int inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs)
static int inboxcount2 (const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
static int inbuf (struct baseio *bio, FILE *fi)
 utility used by inchar(), for base_encode()
static int inchar (struct baseio *bio, FILE *fi)
 utility used by base_encode()
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.
static int last_message_index (struct ast_vm_user *vmu, char *dir)
 Determines the highest message number in use for a given user and mailbox folder.
static int 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 load_config (int reload)
static int load_module (void)
static int make_dir (char *dest, int len, const char *context, const char *ext, const char *folder)
 Creates a file system path expression for a folder within the voicemail data folder and the appropriate context.
static void make_email_file (FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag)
 Creates the email file to be sent to indicate a new voicemail exists for a user.
static 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.
static int manager_list_voicemail_users (struct mansession *s, const struct message *m)
 Manager list voicemail users command.
static void * mb_poll_thread (void *data)
static const char * mbox (struct ast_vm_user *vmu, int id)
static int messagecount (const char *context, const char *mailbox, const char *folder)
static void mwi_sub_destroy (struct mwi_sub *mwi_sub)
static void mwi_sub_event_cb (const struct ast_event *event, void *userdata)
static void mwi_unsub_event_cb (const struct ast_event *event, void *userdata)
static int notify_new_message (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname, const char *flag)
 Sends email notification that a user has a new voicemail waiting for them.
static int ochar (struct baseio *bio, int c, FILE *so)
 utility used by base_encode()
static int open_mailbox (struct vm_state *vms, struct ast_vm_user *vmu, int box)
static int play_message (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int play_message_callerid (struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
static int play_message_category (struct ast_channel *chan, const char *category)
static int play_message_datetime (struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
static int play_message_duration (struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
static int play_record_review (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
static void poll_subscribed_mailbox (struct mwi_sub *mwi_sub)
static void poll_subscribed_mailboxes (void)
static void populate_defaults (struct ast_vm_user *vmu)
 Sets default voicemail system options to a voicemail user.
static void prep_email_sub_vars (struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag)
static void queue_mwi_event (const char *box, int urgent, int new, int old)
static void read_password_from_file (const char *secretfn, char *password, int passwordlen)
static int reload (void)
static void rename_file (char *sfn, char *dfn)
 Renames a message in a mailbox folder.
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.
static void run_externnotify (char *context, char *extension, const char *flag)
static int save_to_folder (struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
static int say_and_wait (struct ast_channel *chan, int num, const char *language)
static int sayname (struct ast_channel *chan, const char *mailbox, const char *context)
static int sendmail (char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag)
static int sendpage (char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
static char * show_users_realtime (int fd, const char *context)
static void start_poll_thread (void)
static void stop_poll_thread (void)
static char * strip_control_and_high (const char *input, char *buf, size_t buflen)
 Strips control and non 7-bit clean characters from input string.
static const char * substitute_escapes (const char *value)
static int unload_module (void)
static int vm_allocate_dh (struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static int vm_authenticate (struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
static int vm_box_exists (struct ast_channel *chan, const char *data)
static int vm_browse_messages (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Top level method to invoke the language variant vm_browse_messages_XX function.
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_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_gr (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Greek 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_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_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_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_zh (struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
 Chinese (Taiwan)syntax for 'You have N messages' greeting.
static void vm_change_password (struct ast_vm_user *vmu, const char *newpassword)
 The handler for the change password option.
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.
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.
static int vm_instructions (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_en (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_zh (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_intro (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_intro_cs (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_de (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_en (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_es (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_fr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_gr (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_he (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_it (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_multilang (struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
static int vm_intro_nl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_no (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pl (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_pt_BR (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_se (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_vi (struct ast_channel *chan, struct vm_state *vms)
static int vm_intro_zh (struct ast_channel *chan, struct vm_state *vms)
static int vm_lock_path (const char *path)
 Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist or any other reason.
static FILE * vm_mkftemp (char *template)
static int vm_newuser (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_options (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int vm_play_folder_name (struct ast_channel *chan, char *mbox)
static int vm_play_folder_name_gr (struct ast_channel *chan, char *box)
static int vm_play_folder_name_pl (struct ast_channel *chan, char *box)
static int vm_play_folder_name_ua (struct ast_channel *chan, char *box)
static int vm_tempgreeting (struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
 The handler for 'record a temporary greeting'.
static int vm_users_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
static int vm_users_data_provider_get_helper (const struct ast_data_search *search, struct ast_data *data_root, struct ast_vm_user *user)
static int vmauthenticate (struct ast_channel *chan, const char *data)
static int vmsayname_exec (struct ast_channel *chan, const char *data)
static struct ast_tmvmu_tm (const struct ast_vm_user *vmu, struct ast_tm *tm)
 fill in *tm for current time according to the proper timezone, if any.
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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", }
static char * addesc = "Comedian Mail"
static unsigned char adsifdn [4] = "\x00\x00\x00\x0F"
static unsigned char adsisec [4] = "\x9B\xDB\xF7\xAC"
static int adsiver = 1
static char * app = "VoiceMail"
static char * app2 = "VoiceMailMain"
static char * app3 = "MailboxExists"
static char * app4 = "VMAuthenticate"
static struct ast_module_infoast_module_info = &__mod_info
static char callcontext [AST_MAX_CONTEXT] = ""
static char charset [32] = "ISO-8859-1"
static char cidinternalcontexts [MAX_NUM_CID_CONTEXTS][64]
static struct ast_cli_entry cli_voicemail []
static char dialcontext [AST_MAX_CONTEXT] = ""
static char * emailbody = NULL
static char emaildateformat [32] = "%A, %B %d, %Y at %r"
static char * emailsubject = NULL
static char exitcontext [AST_MAX_CONTEXT] = ""
static char ext_pass_check_cmd [128]
static char ext_pass_cmd [128]
static char externnotify [160]
static char fromstring [100]
static struct ast_flags globalflags = {0}
ao2_containerinprocess_container
static char listen_control_forward_key [12]
static char listen_control_pause_key [12]
static char listen_control_restart_key [12]
static char listen_control_reverse_key [12]
static char listen_control_stop_key [12]
static char locale [20]
static struct ast_custom_function mailbox_exists_acf
static const char *const mailbox_folders []
static char mailcmd [160]
static int maxdeletedmsg
static int maxgreet
static int maxlogins
static int maxmsg
static int maxsilence
static int minpassword
static struct ast_event_submwi_sub_sub
static struct ast_taskprocessormwi_subscription_tps
static struct ast_event_submwi_unsub_sub
static int my_umask
static char * pagerbody = NULL
static char pagerdateformat [32] = "%A, %B %d, %Y at %r"
static char pagerfromstring [100]
static char * pagersubject = NULL
static int passwordlocation
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER
static unsigned int poll_freq
static ast_mutex_t poll_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static unsigned int poll_mailboxes
static pthread_t poll_thread = AST_PTHREADT_NULL
static unsigned char poll_thread_run
static int pwdchange = PWDCHANGE_INTERNAL
static int saydurationminfo
static char * sayname_app = "VMSayName"
static char serveremail [80]
static int silencethreshold = 128
static int skipms
static struct ast_smdi_interfacesmdi_iface = NULL
static char userscontext [AST_MAX_EXTENSION] = "default"
static struct ast_app_option vm_app_options [128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }}
static struct ast_data_entry vm_data_providers []
static char vm_invalid_password [80] = "vm-invalid-password"
static char vm_mismatch [80] = "vm-mismatch"
static char vm_newpassword [80] = "vm-newpassword"
static char vm_passchanged [80] = "vm-passchanged"
static char vm_password [80] = "vm-password"
static char vm_pls_try_again [80] = "vm-pls-try-again"
static char vm_prepend_timeout [80] = "vm-then-pound"
static char vm_reenterpassword [80] = "vm-reenterpassword"
static char VM_SPOOL_DIR [PATH_MAX]
static struct ast_data_handler vm_users_data_provider
static char vmfmts [80]
static int vmmaxsecs
static int vmminsecs
static double volgain
static char zonetag [80]


Detailed Description

Comedian Mail - Voicemail System.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
unixODBC (http://www.unixodbc.org/)
ExtRef:
A source distribution of University of Washington's IMAP c-client (http://www.washington.edu/imap/)
See also
Note:
For information about voicemail IMAP storage, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage

This module requires res_adsi to load. This needs to be optional during compilation.

This file is now almost impossible to work with, due to all #ifdefs. Feels like the database code before realtime. Someone - please come up with a plan to clean this up.

Definition in file app_voicemail_imapstorage.c.


Define Documentation

#define ASTERISK_USERNAME   "asterisk"

Definition at line 438 of file app_voicemail_imapstorage.c.

#define BASELINELEN   72

Definition at line 461 of file app_voicemail_imapstorage.c.

#define BASEMAXINLINE   256

Definition at line 462 of file app_voicemail_imapstorage.c.

#define CHUNKSIZE   65536

Definition at line 435 of file app_voicemail_imapstorage.c.

#define COMMAND_TIMEOUT   5000

Definition at line 431 of file app_voicemail_imapstorage.c.

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

Definition at line 749 of file app_voicemail_imapstorage.c.

#define DATA_EXPORT_VM_USERS ( USER   ) 

Definition at line 11304 of file app_voicemail_imapstorage.c.

#define DATA_EXPORT_VM_ZONES ( ZONE   ) 

Value:

ZONE(vm_zone, name, AST_DATA_STRING)      \
   ZONE(vm_zone, timezone, AST_DATA_STRING)  \
   ZONE(vm_zone, msg_format, AST_DATA_STRING)

Definition at line 11332 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 443 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 445 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 446 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 444 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 447 of file app_voicemail_imapstorage.c.

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 819 of file app_voicemail_imapstorage.c.

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

Definition at line 750 of file app_voicemail_imapstorage.c.

#define DISPOSE ( a,
 ) 

Definition at line 745 of file app_voicemail_imapstorage.c.

#define ENDL   "\n"

Definition at line 466 of file app_voicemail_imapstorage.c.

#define ERROR_LOCK_PATH   -100

Definition at line 491 of file app_voicemail_imapstorage.c.

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

Definition at line 747 of file app_voicemail_imapstorage.c.

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

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

#define INTRO   "vm-intro"

Definition at line 454 of file app_voicemail_imapstorage.c.

#define MAX_DATETIME_FORMAT   512

Definition at line 469 of file app_voicemail_imapstorage.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 470 of file app_voicemail_imapstorage.c.

#define MAXMSG   100

Definition at line 456 of file app_voicemail_imapstorage.c.

#define MAXMSGLIMIT   9999

Definition at line 457 of file app_voicemail_imapstorage.c.

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 459 of file app_voicemail_imapstorage.c.

#define OPERATOR_EXIT   300

Definition at line 492 of file app_voicemail_imapstorage.c.

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 762 of file app_voicemail_imapstorage.c.

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 761 of file app_voicemail_imapstorage.c.

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

Definition at line 748 of file app_voicemail_imapstorage.c.

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 744 of file app_voicemail_imapstorage.c.

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

Definition at line 452 of file app_voicemail_imapstorage.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 429 of file app_voicemail_imapstorage.c.

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

Definition at line 746 of file app_voicemail_imapstorage.c.

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 771 of file app_voicemail_imapstorage.c.

#define VALID_DTMF   "1234567890*#"

Definition at line 448 of file app_voicemail_imapstorage.c.

#define VM_ALLOCED   (1 << 13)

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

Definition at line 485 of file app_voicemail_imapstorage.c.

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 483 of file app_voicemail_imapstorage.c.

#define VM_DELETE   (1 << 12)

Delete message after sending notification

Definition at line 484 of file app_voicemail_imapstorage.c.

#define VM_DIRECFORWARD   (1 << 10)

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

Definition at line 482 of file app_voicemail_imapstorage.c.

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 476 of file app_voicemail_imapstorage.c.

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 480 of file app_voicemail_imapstorage.c.

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 479 of file app_voicemail_imapstorage.c.

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

Definition at line 490 of file app_voicemail_imapstorage.c.

#define VM_MESSAGEWRAP   (1 << 17)

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

Definition at line 489 of file app_voicemail_imapstorage.c.

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 488 of file app_voicemail_imapstorage.c.

#define VM_OPERATOR   (1 << 1)

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

Definition at line 473 of file app_voicemail_imapstorage.c.

#define VM_PBXSKIP   (1 << 9)

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

Definition at line 481 of file app_voicemail_imapstorage.c.

#define VM_REVIEW   (1 << 0)

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

Definition at line 472 of file app_voicemail_imapstorage.c.

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 474 of file app_voicemail_imapstorage.c.

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 477 of file app_voicemail_imapstorage.c.

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 486 of file app_voicemail_imapstorage.c.

#define VM_SKIPAFTERCMD   (1 << 6)

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

Definition at line 478 of file app_voicemail_imapstorage.c.

#define VM_SVMAIL   (1 << 3)

Allow the user to compose a new VM from within VoicemailMain

Definition at line 475 of file app_voicemail_imapstorage.c.

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 487 of file app_voicemail_imapstorage.c.

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 686 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 437 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 433 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_FILE_MODE   0666

Definition at line 434 of file app_voicemail_imapstorage.c.


Enumeration Type Documentation

enum vm_box

Enumerator:
NEW_FOLDER 
OLD_FOLDER 
WORK_FOLDER 
FAMILY_FOLDER 
FRIENDS_FOLDER 
GREETINGS_FOLDER 

Definition at line 495 of file app_voicemail_imapstorage.c.

00495             {
00496    NEW_FOLDER,
00497    OLD_FOLDER,
00498    WORK_FOLDER,
00499    FAMILY_FOLDER,
00500    FRIENDS_FOLDER,
00501    GREETINGS_FOLDER
00502 };

enum vm_option_args

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 516 of file app_voicemail_imapstorage.c.

00516                     {
00517    OPT_ARG_RECORDGAIN = 0,
00518    OPT_ARG_PLAYFOLDER = 1,
00519    OPT_ARG_DTMFEXIT   = 2,
00520    /* This *must* be the last value in this enum! */
00521    OPT_ARG_ARRAY_SIZE = 3,
00522 };

enum 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 

Definition at line 504 of file app_voicemail_imapstorage.c.

00504                      {
00505    OPT_SILENT =           (1 << 0),
00506    OPT_BUSY_GREETING =    (1 << 1),
00507    OPT_UNAVAIL_GREETING = (1 << 2),
00508    OPT_RECORDGAIN =       (1 << 3),
00509    OPT_PREPEND_MAILBOX =  (1 << 4),
00510    OPT_AUTOPLAY =         (1 << 6),
00511    OPT_DTMFEXIT =         (1 << 7),
00512    OPT_MESSAGE_Urgent =   (1 << 8),
00513    OPT_MESSAGE_PRIORITY = (1 << 9)
00514 };

enum vm_passwordlocation

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 524 of file app_voicemail_imapstorage.c.

00524                          {
00525    OPT_PWLOC_VOICEMAILCONF = 0,
00526    OPT_PWLOC_SPOOLDIR      = 1,
00527    OPT_PWLOC_USERSCONF     = 2,
00528 };


Function Documentation

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

Definition at line 5380 of file app_voicemail_imapstorage.c.

References ast_strlen_zero(), and VM_SPOOL_DIR.

05381 {
05382    DIR *dir;
05383    struct dirent *de;
05384    char fn[256];
05385    int ret = 0;
05386 
05387    /* If no mailbox, return immediately */
05388    if (ast_strlen_zero(mailbox))
05389       return 0;
05390 
05391    if (ast_strlen_zero(folder))
05392       folder = "INBOX";
05393    if (ast_strlen_zero(context))
05394       context = "default";
05395 
05396    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05397 
05398    if (!(dir = opendir(fn)))
05399       return 0;
05400 
05401    while ((de = readdir(dir))) {
05402       if (!strncasecmp(de->d_name, "msg", 3)) {
05403          if (shortcircuit) {
05404             ret = 1;
05405             break;
05406          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05407             ret++;
05408          }
05409       }
05410    }
05411 
05412    closedir(dir);
05413 
05414    return ret;
05415 }

static void __reg_module ( void   )  [static]

Definition at line 13629 of file app_voicemail_imapstorage.c.

static void __unreg_module ( void   )  [static]

Definition at line 13629 of file app_voicemail_imapstorage.c.

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

Definition at line 11008 of file app_voicemail_imapstorage.c.

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strlen_zero(), find_user(), LOG_ERROR, and mbox().

11009 {
11010    struct ast_vm_user svm;
11011    AST_DECLARE_APP_ARGS(arg,
11012       AST_APP_ARG(mbox);
11013       AST_APP_ARG(context);
11014    );
11015 
11016    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11017 
11018    if (ast_strlen_zero(arg.mbox)) {
11019       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11020       return -1;
11021    }
11022 
11023    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11024    return 0;
11025 }

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

Definition at line 11829 of file app_voicemail_imapstorage.c.

References adsifdn, adsisec, adsiver, append_mailbox(), apply_options_full(), ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, ast_dsp_get_threshold_from_settings(), ast_false(), ast_format_str_reduce(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_LOG_DEBUG, AST_LOG_ERROR, ast_malloc, AST_PTHREADT_NULL, ast_set2_flag, ast_smdi_interface_find(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, 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(), vm_zone::list, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, locale, LOG_ERROR, mailcmd, MAX_NUM_CID_CONTEXTS, maxdeletedmsg, maxgreet, maxlogins, MAXMSG, maxmsg, MAXMSGLIMIT, maxsilence, MINPASSWORD, minpassword, vm_zone::msg_format, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, passwordlocation, poll_freq, poll_mailboxes, poll_thread, populate_defaults(), pwdchange, PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), saydurationminfo, SENDMAIL, serveremail, silencethreshold, skipms, smdi_iface, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, userscontext, var, VM_ATTACH, VM_DIRECFORWARD, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_FWDURGAUTO, vm_invalid_password, VM_MESSAGEWRAP, vm_mismatch, VM_MOVEHEARD, vm_newpassword, 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.

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

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 4794 of file app_voicemail_imapstorage.c.

References ast_debug, ast_log(), ast_safe_system(), base_encode(), ast_vm_user::context, create_dirpath(), ENDL, LOG_WARNING, ast_vm_user::mailbox, my_umask, VOICEMAIL_FILE_MODE, and ast_vm_user::volgain.

04795 {
04796    char tmpdir[256], newtmp[256];
04797    char fname[256];
04798    char tmpcmd[256];
04799    int tmpfd = -1;
04800    int soxstatus = 0;
04801 
04802    /* Eww. We want formats to tell us their own MIME type */
04803    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04804 
04805    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04806       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04807       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04808       tmpfd = mkstemp(newtmp);
04809       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04810       ast_debug(3, "newtmp: %s\n", newtmp);
04811       if (tmpfd > -1) {
04812          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04813          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04814             attach = newtmp;
04815             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04816          } else {
04817             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04818                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04819             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04820          }
04821       }
04822    }
04823    fprintf(p, "--%s" ENDL, bound);
04824    if (msgnum > -1)
04825       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04826    else
04827       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04828    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04829    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04830    if (msgnum > -1)
04831       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04832    else
04833       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04834    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04835    base_encode(fname, p);
04836    if (last)
04837       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04838    if (tmpfd > -1) {
04839       if (soxstatus == 0) {
04840          unlink(fname);
04841       }
04842       close(tmpfd);
04843       unlink(newtmp);
04844    }
04845    return 0;
04846 }

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

Definition at line 6398 of file app_voicemail_imapstorage.c.

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

06399 {
06400    int x;
06401    if (!ast_adsi_available(chan))
06402       return;
06403    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06404    if (x < 0)
06405       return;
06406    if (!x) {
06407       if (adsi_load_vmail(chan, useadsi)) {
06408          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06409          return;
06410       }
06411    } else
06412       *useadsi = 1;
06413 }

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

Definition at line 6587 of file app_voicemail_imapstorage.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available(), and vm_state::curmsg.

06588 {
06589    int bytes = 0;
06590    unsigned char buf[256];
06591    unsigned char keys[8];
06592 
06593    int x;
06594 
06595    if (!ast_adsi_available(chan))
06596       return;
06597 
06598    /* New meaning for keys */
06599    for (x = 0; x < 5; x++)
06600       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06601 
06602    keys[6] = 0x0;
06603    keys[7] = 0x0;
06604 
06605    if (!vms->curmsg) {
06606       /* No prev key, provide "Folder" instead */
06607       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06608    }
06609    if (vms->curmsg >= vms->lastmsg) {
06610       /* If last message ... */
06611       if (vms->curmsg) {
06612          /* but not only message, provide "Folder" instead */
06613          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06614       } else {
06615          /* Otherwise if only message, leave blank */
06616          keys[3] = 1;
06617       }
06618    }
06619 
06620    /* If deleted, show "undeleted" */
06621    if (vms->deleted[vms->curmsg]) 
06622       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06623 
06624    /* Except "Exit" */
06625    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06626    bytes += ast_adsi_set_keys(buf + bytes, keys);
06627    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06628 
06629    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06630 }

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

Definition at line 6463 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_KEY_APPS, ADSI_KEY_SKT, ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), and ast_adsi_voice_mode().

06464 {
06465    unsigned char buf[256];
06466    int bytes = 0;
06467    unsigned char keys[8];
06468    int x, y;
06469 
06470    if (!ast_adsi_available(chan))
06471       return;
06472 
06473    for (x = 0; x < 5; x++) {
06474       y = ADSI_KEY_APPS + 12 + start + x;
06475       if (y > ADSI_KEY_APPS + 12 + 4)
06476          y = 0;
06477       keys[x] = ADSI_KEY_SKT | y;
06478    }
06479    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06480    keys[6] = 0;
06481    keys[7] = 0;
06482 
06483    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06484    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06485    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06486    bytes += ast_adsi_set_keys(buf + bytes, keys);
06487    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06488 
06489    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06490 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

Definition at line 6735 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, ADSI_JUST_LEFT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), and ast_adsi_voice_mode().

06736 {
06737    unsigned char buf[256];
06738    int bytes = 0;
06739 
06740    if (!ast_adsi_available(chan))
06741       return;
06742    bytes += adsi_logo(buf + bytes);
06743    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06744    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06745    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06746    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06747 
06748    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06749 }

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

Definition at line 6269 of file app_voicemail_imapstorage.c.

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

06270 {
06271    unsigned char buf[256];
06272    int bytes = 0;
06273    int x;
06274    char num[5];
06275 
06276    *useadsi = 0;
06277    bytes += ast_adsi_data_mode(buf + bytes);
06278    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06279 
06280    bytes = 0;
06281    bytes += adsi_logo(buf);
06282    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06283 #ifdef DISPLAY
06284    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06285 #endif
06286    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06287    bytes += ast_adsi_data_mode(buf + bytes);
06288    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06289 
06290    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06291       bytes = 0;
06292       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06293       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06294       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06295       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06296       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06297       return 0;
06298    }
06299 
06300 #ifdef DISPLAY
06301    /* Add a dot */
06302    bytes = 0;
06303    bytes += ast_adsi_logo(buf);
06304    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06305    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06306    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06307    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06308 #endif
06309    bytes = 0;
06310    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06311    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06312    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06313    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06314    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06315    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06316    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06317 
06318 #ifdef DISPLAY
06319    /* Add another dot */
06320    bytes = 0;
06321    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06322    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06323 
06324    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06325    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06326 #endif
06327 
06328    bytes = 0;
06329    /* These buttons we load but don't use yet */
06330    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06331    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06332    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06333    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06334    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06335    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06336    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06337 
06338 #ifdef DISPLAY
06339    /* Add another dot */
06340    bytes = 0;
06341    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06342    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06343    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06344 #endif
06345 
06346    bytes = 0;
06347    for (x = 0; x < 5; x++) {
06348       snprintf(num, sizeof(num), "%d", x);
06349       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06350    }
06351    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06352    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06353 
06354 #ifdef DISPLAY
06355    /* Add another dot */
06356    bytes = 0;
06357    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06358    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06359    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06360 #endif
06361 
06362    if (ast_adsi_end_download(chan)) {
06363       bytes = 0;
06364       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06365       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06366       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06367       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06368       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06369       return 0;
06370    }
06371    bytes = 0;
06372    bytes += ast_adsi_download_disconnect(buf + bytes);
06373    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06374    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06375 
06376    ast_debug(1, "Done downloading scripts...\n");
06377 
06378 #ifdef DISPLAY
06379    /* Add last dot */
06380    bytes = 0;
06381    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06382    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06383 #endif
06384    ast_debug(1, "Restarting session...\n");
06385 
06386    bytes = 0;
06387    /* Load the session now */
06388    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06389       *useadsi = 1;
06390       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06391    } else
06392       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06393 
06394    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06395    return 0;
06396 }

static void adsi_login ( struct ast_channel chan  )  [static]

Definition at line 6415 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_DIR_FROM_LEFT, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_input_control(), ast_adsi_input_format(), ast_adsi_load_soft_key(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), and ast_adsi_voice_mode().

06416 {
06417    unsigned char buf[256];
06418    int bytes = 0;
06419    unsigned char keys[8];
06420    int x;
06421    if (!ast_adsi_available(chan))
06422       return;
06423 
06424    for (x = 0; x < 8; x++)
06425       keys[x] = 0;
06426    /* Set one key for next */
06427    keys[3] = ADSI_KEY_APPS + 3;
06428 
06429    bytes += adsi_logo(buf + bytes);
06430    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06431    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06432    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06433    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06434    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06435    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06436    bytes += ast_adsi_set_keys(buf + bytes, keys);
06437    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06438    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06439 }

static int adsi_logo ( unsigned char *  buf  )  [static]

Definition at line 6261 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display().

06262 {
06263    int bytes = 0;
06264    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06265    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06266    return bytes;
06267 }

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

Definition at line 6492 of file app_voicemail_imapstorage.c.

References ADSI_KEY_APPS, ADSI_KEY_SKT, ast_adsi_available(), ast_copy_string(), ast_strlen_zero(), buf1, buf2, vm_state::curmsg, vm_state::fn, name, and strsep().

06493 {
06494    int bytes = 0;
06495    unsigned char buf[256]; 
06496    char buf1[256], buf2[256];
06497    char fn2[PATH_MAX];
06498 
06499    char cid[256] = "";
06500    char *val;
06501    char *name, *num;
06502    char datetime[21] = "";
06503    FILE *f;
06504 
06505    unsigned char keys[8];
06506 
06507    int x;
06508 
06509    if (!ast_adsi_available(chan))
06510       return;
06511 
06512    /* Retrieve important info */
06513    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06514    f = fopen(fn2, "r");
06515    if (f) {
06516       while (!feof(f)) {   
06517          if (!fgets((char *) buf, sizeof(buf), f)) {
06518             continue;
06519          }
06520          if (!feof(f)) {
06521             char *stringp = NULL;
06522             stringp = (char *) buf;
06523             strsep(&stringp, "=");
06524             val = strsep(&stringp, "=");
06525             if (!ast_strlen_zero(val)) {
06526                if (!strcmp((char *) buf, "callerid"))
06527                   ast_copy_string(cid, val, sizeof(cid));
06528                if (!strcmp((char *) buf, "origdate"))
06529                   ast_copy_string(datetime, val, sizeof(datetime));
06530             }
06531          }
06532       }
06533       fclose(f);
06534    }
06535    /* New meaning for keys */
06536    for (x = 0; x < 5; x++)
06537       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06538    keys[6] = 0x0;
06539    keys[7] = 0x0;
06540 
06541    if (!vms->curmsg) {
06542       /* No prev key, provide "Folder" instead */
06543       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06544    }
06545    if (vms->curmsg >= vms->lastmsg) {
06546       /* If last message ... */
06547       if (vms->curmsg) {
06548          /* but not only message, provide "Folder" instead */
06549          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06550          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06551 
06552       } else {
06553          /* Otherwise if only message, leave blank */
06554          keys[3] = 1;
06555       }
06556    }
06557 
06558    if (!ast_strlen_zero(cid)) {
06559       ast_callerid_parse(cid, &name, &num);
06560       if (!name)
06561          name = num;
06562    } else
06563       name = "Unknown Caller";
06564 
06565    /* If deleted, show "undeleted" */
06566 
06567    if (vms->deleted[vms->curmsg])
06568       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06569 
06570    /* Except "Exit" */
06571    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06572    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06573       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06574    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06575 
06576    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06577    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06578    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06579    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06580    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06581    bytes += ast_adsi_set_keys(buf + bytes, keys);
06582    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06583 
06584    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06585 }

static void adsi_password ( struct ast_channel chan  )  [static]

Definition at line 6441 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_DIR_FROM_LEFT, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_input_control(), ast_adsi_input_format(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), and ast_adsi_voice_mode().

06442 {
06443    unsigned char buf[256];
06444    int bytes = 0;
06445    unsigned char keys[8];
06446    int x;
06447    if (!ast_adsi_available(chan))
06448       return;
06449 
06450    for (x = 0; x < 8; x++)
06451       keys[x] = 0;
06452    /* Set one key for next */
06453    keys[3] = ADSI_KEY_APPS + 3;
06454 
06455    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06456    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06457    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06458    bytes += ast_adsi_set_keys(buf + bytes, keys);
06459    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06460    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06461 }

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

Definition at line 6632 of file app_voicemail_imapstorage.c.

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

06633 {
06634    unsigned char buf[256] = "";
06635    char buf1[256] = "", buf2[256] = "";
06636    int bytes = 0;
06637    unsigned char keys[8];
06638    int x;
06639 
06640    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06641    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06642    if (!ast_adsi_available(chan))
06643       return;
06644    if (vms->newmessages) {
06645       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06646       if (vms->oldmessages) {
06647          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06648          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06649       } else {
06650          snprintf(buf2, sizeof(buf2), "%s.", newm);
06651       }
06652    } else if (vms->oldmessages) {
06653       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06654       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06655    } else {
06656       strcpy(buf1, "You have no messages.");
06657       buf2[0] = ' ';
06658       buf2[1] = '\0';
06659    }
06660    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06661    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06662    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06663 
06664    for (x = 0; x < 6; x++)
06665       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06666    keys[6] = 0;
06667    keys[7] = 0;
06668 
06669    /* Don't let them listen if there are none */
06670    if (vms->lastmsg < 0)
06671       keys[0] = 1;
06672    bytes += ast_adsi_set_keys(buf + bytes, keys);
06673 
06674    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06675 
06676    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06677 }

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

Definition at line 6679 of file app_voicemail_imapstorage.c.

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

06680 {
06681    unsigned char buf[256] = "";
06682    char buf1[256] = "", buf2[256] = "";
06683    int bytes = 0;
06684    unsigned char keys[8];
06685    int x;
06686 
06687    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06688 
06689    if (!ast_adsi_available(chan))
06690       return;
06691 
06692    /* Original command keys */
06693    for (x = 0; x < 6; x++)
06694       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06695 
06696    keys[6] = 0;
06697    keys[7] = 0;
06698 
06699    if ((vms->lastmsg + 1) < 1)
06700       keys[0] = 0;
06701 
06702    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06703       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06704 
06705    if (vms->lastmsg + 1)
06706       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06707    else
06708       strcpy(buf2, "no messages.");
06709    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06710    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06711    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06712    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06713    bytes += ast_adsi_set_keys(buf + bytes, keys);
06714 
06715    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06716 
06717    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06718    
06719 }

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 13191 of file app_voicemail_imapstorage.c.

References ast_callerid_parse(), ast_config_destroy(), ast_config_load, ast_log(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_test_suite_event_notify, ast_variable_retrieve(), ast_verb, ast_waitfordigit(), ast_vm_user::callback, CONFIG_FLAG_NOCACHE, config_flags, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, ast_vm_user::dialout, dialout(), DISPOSE, find_user(), vm_state::fn, vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, make_file(), name, play_message_callerid(), play_message_datetime(), RETRIEVE, vm_state::starting, and wait_file().

13192 {
13193    int res = 0;
13194    char filename[PATH_MAX];
13195    struct ast_config *msg_cfg = NULL;
13196    const char *origtime, *context;
13197    char *name, *num;
13198    int retries = 0;
13199    char *cid;
13200    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
13201 
13202    vms->starting = 0; 
13203 
13204    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13205 
13206    /* Retrieve info from VM attribute file */
13207    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
13208    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
13209    msg_cfg = ast_config_load(filename, config_flags);
13210    DISPOSE(vms->curdir, vms->curmsg);
13211    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
13212       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
13213       return 0;
13214    }
13215 
13216    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
13217       ast_config_destroy(msg_cfg);
13218       return 0;
13219    }
13220 
13221    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
13222 
13223    context = ast_variable_retrieve(msg_cfg, "message", "context");
13224    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
13225       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
13226    switch (option) {
13227    case 3: /* Play message envelope */
13228       if (!res)
13229          res = play_message_datetime(chan, vmu, origtime, filename);
13230       if (!res)
13231          res = play_message_callerid(chan, vms, cid, context, 0);
13232 
13233       res = 't';
13234       break;
13235 
13236    case 2:  /* Call back */
13237 
13238       if (ast_strlen_zero(cid))
13239          break;
13240 
13241       ast_callerid_parse(cid, &name, &num);
13242       while ((res > -1) && (res != 't')) {
13243          switch (res) {
13244          case '1':
13245             if (num) {
13246                /* Dial the CID number */
13247                res = dialout(chan, vmu, num, vmu->callback);
13248                if (res) {
13249                   ast_config_destroy(msg_cfg);
13250                   return 9;
13251                }
13252             } else {
13253                res = '2';
13254             }
13255             break;
13256 
13257          case '2':
13258             /* Want to enter a different number, can only do this if there's a dialout context for this user */
13259             if (!ast_strlen_zero(vmu->dialout)) {
13260                res = dialout(chan, vmu, NULL, vmu->dialout);
13261                if (res) {
13262                   ast_config_destroy(msg_cfg);
13263                   return 9;
13264                }
13265             } else {
13266                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
13267                res = ast_play_and_wait(chan, "vm-sorry");
13268             }
13269             ast_config_destroy(msg_cfg);
13270             return res;
13271          case '*':
13272             res = 't';
13273             break;
13274          case '3':
13275          case '4':
13276          case '5':
13277          case '6':
13278          case '7':
13279          case '8':
13280          case '9':
13281          case '0':
13282 
13283             res = ast_play_and_wait(chan, "vm-sorry");
13284             retries++;
13285             break;
13286          default:
13287             if (num) {
13288                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
13289                res = ast_play_and_wait(chan, "vm-num-i-have");
13290                if (!res)
13291                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
13292                if (!res)
13293                   res = ast_play_and_wait(chan, "vm-tocallnum");
13294                /* Only prompt for a caller-specified number if there is a dialout context specified */
13295                if (!ast_strlen_zero(vmu->dialout)) {
13296                   if (!res)
13297                      res = ast_play_and_wait(chan, "vm-calldiffnum");
13298                }
13299             } else {
13300                res = ast_play_and_wait(chan, "vm-nonumber");
13301                if (!ast_strlen_zero(vmu->dialout)) {
13302                   if (!res)
13303                      res = ast_play_and_wait(chan, "vm-toenternumber");
13304                }
13305             }
13306             if (!res) {
13307                res = ast_play_and_wait(chan, "vm-star-cancel");
13308             }
13309             if (!res) {
13310                res = ast_waitfordigit(chan, 6000);
13311             }
13312             if (!res) {
13313                retries++;
13314                if (retries > 3) {
13315                   res = 't';
13316                }
13317             }
13318             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
13319             break; 
13320             
13321          }
13322          if (res == 't')
13323             res = 0;
13324          else if (res == '*')
13325             res = -1;
13326       }
13327       break;
13328       
13329    case 1:  /* Reply */
13330       /* Send reply directly to sender */
13331       if (ast_strlen_zero(cid))
13332          break;
13333 
13334       ast_callerid_parse(cid, &name, &num);
13335       if (!num) {
13336          ast_verb(3, "No CID number available, no reply sent\n");
13337          if (!res)
13338             res = ast_play_and_wait(chan, "vm-nonumber");
13339          ast_config_destroy(msg_cfg);
13340          return res;
13341       } else {
13342          struct ast_vm_user vmu2;
13343          if (find_user(&vmu2, vmu->context, num)) {
13344             struct leave_vm_options leave_options;
13345             char mailbox[AST_MAX_EXTENSION * 2 + 2];
13346             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
13347 
13348             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
13349             
13350             memset(&leave_options, 0, sizeof(leave_options));
13351             leave_options.record_gain = record_gain;
13352             res = leave_voicemail(chan, mailbox, &leave_options);
13353             if (!res)
13354                res = 't';
13355             ast_config_destroy(msg_cfg);
13356             return res;
13357          } else {
13358             /* Sender has no mailbox, can't reply */
13359             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
13360             ast_play_and_wait(chan, "vm-nobox");
13361             res = 't';
13362             ast_config_destroy(msg_cfg);
13363             return res;
13364          }
13365       } 
13366       res = 0;
13367 
13368       break;
13369    }
13370 
13371 #ifndef IMAP_STORAGE
13372    ast_config_destroy(msg_cfg);
13373 
13374    if (!res) {
13375       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13376       vms->heard[msg] = 1;
13377       res = wait_file(chan, vms, vms->fn);
13378    }
13379 #endif
13380    return res;
13381 }

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

Definition at line 10735 of file app_voicemail_imapstorage.c.

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

10736 {
10737    /* Assumes lock is already held */
10738    char *tmp;
10739    char *stringp;
10740    char *s;
10741    struct ast_vm_user *vmu;
10742    char *mailbox_full;
10743    int new = 0, old = 0, urgent = 0;
10744    char secretfn[PATH_MAX] = "";
10745 
10746    tmp = ast_strdupa(data);
10747 
10748    if (!(vmu = find_or_create(context, box)))
10749       return -1;
10750 
10751    populate_defaults(vmu);
10752 
10753    stringp = tmp;
10754    if ((s = strsep(&stringp, ","))) {
10755       if (!ast_strlen_zero(s) && s[0] == '*') {
10756          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
10757             "\n\tmust be reset in voicemail.conf.\n", box);
10758       }
10759       /* assign password regardless of validity to prevent NULL password from being assigned */
10760       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10761    }
10762    if (stringp && (s = strsep(&stringp, ","))) {
10763       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10764    }
10765    if (stringp && (s = strsep(&stringp, ","))) {
10766       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10767    }
10768    if (stringp && (s = strsep(&stringp, ","))) {
10769       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10770    }
10771    if (stringp && (s = strsep(&stringp, ","))) {
10772       apply_options(vmu, s);
10773    }
10774 
10775    switch (vmu->passwordlocation) {
10776    case OPT_PWLOC_SPOOLDIR:
10777       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10778       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10779    }
10780 
10781    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10782    strcpy(mailbox_full, box);
10783    strcat(mailbox_full, "@");
10784    strcat(mailbox_full, context);
10785 
10786    inboxcount2(mailbox_full, &urgent, &new, &old);
10787    queue_mwi_event(mailbox_full, urgent, new, old);
10788 
10789    return 0;
10790 }

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

Sets a a specific property value.

Parameters:
vmu The voicemail user object to work with.
var The name of the property to be set.
value The 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 1064 of file app_voicemail_imapstorage.c.

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

01065 {
01066    int x;
01067    if (!strcasecmp(var, "attach")) {
01068       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
01069    } else if (!strcasecmp(var, "attachfmt")) {
01070       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
01071    } else if (!strcasecmp(var, "serveremail")) {
01072       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
01073    } else if (!strcasecmp(var, "emailbody")) {
01074       vmu->emailbody = ast_strdup(substitute_escapes(value));
01075    } else if (!strcasecmp(var, "emailsubject")) {
01076       vmu->emailsubject = ast_strdup(substitute_escapes(value));
01077    } else if (!strcasecmp(var, "language")) {
01078       ast_copy_string(vmu->language, value, sizeof(vmu->language));
01079    } else if (!strcasecmp(var, "tz")) {
01080       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
01081    } else if (!strcasecmp(var, "locale")) {
01082       ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
01083 #ifdef IMAP_STORAGE
01084    } else if (!strcasecmp(var, "imapuser")) {
01085       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
01086       vmu->imapversion = imapversion;
01087    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
01088       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
01089       vmu->imapversion = imapversion;
01090    } else if (!strcasecmp(var, "imapfolder")) {
01091       ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
01092    } else if (!strcasecmp(var, "imapvmshareid")) {
01093       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
01094       vmu->imapversion = imapversion;
01095 #endif
01096    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
01097       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
01098    } else if (!strcasecmp(var, "saycid")){
01099       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
01100    } else if (!strcasecmp(var, "sendvoicemail")){
01101       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
01102    } else if (!strcasecmp(var, "review")){
01103       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
01104    } else if (!strcasecmp(var, "tempgreetwarn")){
01105       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
01106    } else if (!strcasecmp(var, "messagewrap")){
01107       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
01108    } else if (!strcasecmp(var, "operator")) {
01109       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
01110    } else if (!strcasecmp(var, "envelope")){
01111       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
01112    } else if (!strcasecmp(var, "moveheard")){
01113       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
01114    } else if (!strcasecmp(var, "sayduration")){
01115       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
01116    } else if (!strcasecmp(var, "saydurationm")){
01117       if (sscanf(value, "%30d", &x) == 1) {
01118          vmu->saydurationm = x;
01119       } else {
01120          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
01121       }
01122    } else if (!strcasecmp(var, "forcename")){
01123       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01124    } else if (!strcasecmp(var, "forcegreetings")){
01125       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01126    } else if (!strcasecmp(var, "callback")) {
01127       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01128    } else if (!strcasecmp(var, "dialout")) {
01129       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01130    } else if (!strcasecmp(var, "exitcontext")) {
01131       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01132    } else if (!strcasecmp(var, "minsecs")) {
01133       if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
01134          vmu->minsecs = x;
01135       } else {
01136          ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
01137          vmu->minsecs = vmminsecs;
01138       }
01139    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01140       vmu->maxsecs = atoi(value);
01141       if (vmu->maxsecs <= 0) {
01142          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01143          vmu->maxsecs = vmmaxsecs;
01144       } else {
01145          vmu->maxsecs = atoi(value);
01146       }
01147       if (!strcasecmp(var, "maxmessage"))
01148          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01149    } else if (!strcasecmp(var, "maxmsg")) {
01150       vmu->maxmsg = atoi(value);
01151       /* Accept maxmsg=0 (Greetings only voicemail) */
01152       if (vmu->maxmsg < 0) {
01153          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01154          vmu->maxmsg = MAXMSG;
01155       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01156          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01157          vmu->maxmsg = MAXMSGLIMIT;
01158       }
01159    } else if (!strcasecmp(var, "nextaftercmd")) {
01160       ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
01161    } else if (!strcasecmp(var, "backupdeleted")) {
01162       if (sscanf(value, "%30d", &x) == 1)
01163          vmu->maxdeletedmsg = x;
01164       else if (ast_true(value))
01165          vmu->maxdeletedmsg = MAXMSG;
01166       else
01167          vmu->maxdeletedmsg = 0;
01168 
01169       if (vmu->maxdeletedmsg < 0) {
01170          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01171          vmu->maxdeletedmsg = MAXMSG;
01172       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01173          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01174          vmu->maxdeletedmsg = MAXMSGLIMIT;
01175       }
01176    } else if (!strcasecmp(var, "volgain")) {
01177       sscanf(value, "%30lf", &vmu->volgain);
01178    } else if (!strcasecmp(var, "passwordlocation")) {
01179       if (!strcasecmp(value, "spooldir")) {
01180          vmu->passwordlocation = OPT_PWLOC_SPOOLDIR;
01181       } else {
01182          vmu->passwordlocation = OPT_PWLOC_VOICEMAILCONF;
01183       }
01184    } else if (!strcasecmp(var, "options")) {
01185       apply_options(vmu, value);
01186    }
01187 }

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

Destructively Parse options and apply.

Definition at line 1305 of file app_voicemail_imapstorage.c.

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

01306 {  
01307    char *stringp;
01308    char *s;
01309    char *var, *value;
01310    stringp = ast_strdupa(options);
01311    while ((s = strsep(&stringp, "|"))) {
01312       value = s;
01313       if ((var = strsep(&value, "=")) && value) {
01314          apply_option(vmu, var, value);
01315       }
01316    }  
01317 }

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 1324 of file app_voicemail_imapstorage.c.

References ast_copy_string(), ast_log(), ast_strlen_zero(), LOG_WARNING, ast_vm_user::mailbox, ast_vm_user::password, and var.

01325 {
01326    for (; var; var = var->next) {
01327       if (!strcasecmp(var->name, "vmsecret")) {
01328          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01329       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01330          if (ast_strlen_zero(retval->password)) {
01331             if (!ast_strlen_zero(var->value) && var->value[0] == '*') {
01332                ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
01333                   "\n\tmust be reset in voicemail.conf.\n", retval->mailbox);
01334             } else {
01335                ast_copy_string(retval->password, var->value, sizeof(retval->password));
01336             }
01337          }
01338       } else if (!strcasecmp(var->name, "uniqueid")) {
01339          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01340       } else if (!strcasecmp(var->name, "pager")) {
01341          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01342       } else if (!strcasecmp(var->name, "email")) {
01343          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01344       } else if (!strcasecmp(var->name, "fullname")) {
01345          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01346       } else if (!strcasecmp(var->name, "context")) {
01347          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01348       } else if (!strcasecmp(var->name, "emailsubject")) {
01349          ast_free(retval->emailsubject);
01350          retval->emailsubject = ast_strdup(substitute_escapes(var->value));
01351       } else if (!strcasecmp(var->name, "emailbody")) {
01352          ast_free(retval->emailbody);
01353          retval->emailbody = ast_strdup(substitute_escapes(var->value));
01354 #ifdef IMAP_STORAGE
01355       } else if (!strcasecmp(var->name, "imapuser")) {
01356          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01357          retval->imapversion = imapversion;
01358       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01359          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01360          retval->imapversion = imapversion;
01361       } else if (!strcasecmp(var->name, "imapfolder")) {
01362          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01363       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01364          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01365          retval->imapversion = imapversion;
01366 #endif
01367       } else
01368          apply_option(retval, var->name, var->value);
01369    }
01370 }

AST_DATA_STRUCTURE ( vm_zone  ,
DATA_EXPORT_VM_ZONES   
)

AST_DATA_STRUCTURE ( ast_vm_user  ,
DATA_EXPORT_VM_USERS   
)

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:
end An expandable buffer for holding the result
maxlen Always zero, but see
See also:
ast_str
Parameters:
start A string to be encoded
preamble The length of the first line already used for this string, to ensure that each line maintains a maximum length of 76 chars.
postamble the length of any additional characters appended to the line, used to ensure proper field wrapping.
Return values:
The encoded string.

Definition at line 4469 of file app_voicemail_imapstorage.c.

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

04470 {
04471    struct ast_str *tmp = ast_str_alloca(80);
04472    int first_section = 1;
04473 
04474    ast_str_reset(*end);
04475    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04476    for (; *start; start++) {
04477       int need_encoding = 0;
04478       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04479          need_encoding = 1;
04480       }
04481       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04482          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04483          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04484          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04485          /* Start new line */
04486          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04487          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04488          first_section = 0;
04489       }
04490       if (need_encoding && *start == ' ') {
04491          ast_str_append(&tmp, -1, "_");
04492       } else if (need_encoding) {
04493          ast_str_append(&tmp, -1, "=%hhX", *start);
04494       } else {
04495          ast_str_append(&tmp, -1, "%c", *start);
04496       }
04497    }
04498    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04499    return ast_str_buffer(*end);
04500 }

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:
from The string to work with.
buf The buffer into which to write the modified quoted string.
maxlen Always zero, but see
See also:
ast_str
Returns:
The destination string with quotes wrapped on it (the to field).

Definition at line 4397 of file app_voicemail_imapstorage.c.

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

04398 {
04399    const char *ptr;
04400 
04401    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04402    ast_str_set(buf, maxlen, "\"");
04403    for (ptr = from; *ptr; ptr++) {
04404       if (*ptr == '"' || *ptr == '\\') {
04405          ast_str_append(buf, maxlen, "\\%c", *ptr);
04406       } else {
04407          ast_str_append(buf, maxlen, "%c", *ptr);
04408       }
04409    }
04410    ast_str_append(buf, maxlen, "\"");
04411 
04412    return ast_str_buffer(*buf);
04413 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10792 of file app_voicemail_imapstorage.c.

References apply_options(), ast_calloc, ast_set_flag, AST_TEST_FAIL, ast_test_flag, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, free_user(), OPT_PWLOC_SPOOLDIR, populate_defaults(), TEST_EXECUTE, TEST_INIT, VM_ALLOCED, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_FORCEGREET, VM_FORCENAME, VM_MESSAGEWRAP, VM_MOVEHEARD, VM_OPERATOR, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SKIPAFTERCMD, VM_SVMAIL, and VM_TEMPGREETWARN.

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

static int base_encode ( char *  filename,
FILE *  so 
) [static]

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

Parameters:
filename The path to the file to be encoded. Must be readable, file is opened in read mode.
so A FILE handle to the output file to receive the base 64 encoded contents of the input file, identified by filename.
TODO: shouldn't this (and the above 3 support functions) be put into some kind of external utility location, such as funcs/func_base64.c ?

Returns:
zero on success, -1 on error.

Definition at line 4273 of file app_voicemail_imapstorage.c.

References ast_log(), BASEMAXINLINE, ENDL, errno, inchar(), and ochar().

04274 {
04275    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04276       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04277       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04278       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04279    int i, hiteof = 0;
04280    FILE *fi;
04281    struct baseio bio;
04282 
04283    memset(&bio, 0, sizeof(bio));
04284    bio.iocp = BASEMAXINLINE;
04285 
04286    if (!(fi = fopen(filename, "rb"))) {
04287       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04288       return -1;
04289    }
04290 
04291    while (!hiteof){
04292       unsigned char igroup[3], ogroup[4];
04293       int c, n;
04294 
04295       memset(igroup, 0, sizeof(igroup));
04296 
04297       for (n = 0; n < 3; n++) {
04298          if ((c = inchar(&bio, fi)) == EOF) {
04299             hiteof = 1;
04300             break;
04301          }
04302 
04303          igroup[n] = (unsigned char) c;
04304       }
04305 
04306       if (n > 0) {
04307          ogroup[0]= dtable[igroup[0] >> 2];
04308          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04309          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04310          ogroup[3]= dtable[igroup[2] & 0x3F];
04311 
04312          if (n < 3) {
04313             ogroup[3] = '=';
04314 
04315             if (n < 2)
04316                ogroup[2] = '=';
04317          }
04318 
04319          for (i = 0; i < 4; i++)
04320             ochar(&bio, ogroup[i], so);
04321       }
04322    }
04323 
04324    fclose(fi);
04325    
04326    if (fputs(ENDL, so) == EOF) {
04327       return 0;
04328    }
04329 
04330    return 1;
04331 }

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:
vmu The voicemail user to change the password for.
password The 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 1283 of file app_voicemail_imapstorage.c.

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

01284 {
01285    int res = -1;
01286    if (!strcmp(vmu->password, password)) {
01287       /* No change (but an update would return 0 rows updated, so we opt out here) */
01288       return 0;
01289    }
01290 
01291    if (strlen(password) > 10) {
01292       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01293    }
01294    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01295       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: realtime engine updated with new password\r\nPasswordSource: realtime");
01296       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01297       res = 0;
01298    }
01299    return res;
01300 }

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 4442 of file app_voicemail_imapstorage.c.

04443 {
04444    for (; *str; str++) {
04445       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04446          return 1;
04447       }
04448    }
04449    return 0;
04450 }

static int check_password ( struct ast_vm_user vmu,
char *  password 
) [static]

Check that password meets minimum required length.

Parameters:
vmu The voicemail user to change the password for.
password The password string to check
Returns:
zero on ok, 1 on not ok.

Definition at line 1242 of file app_voicemail_imapstorage.c.

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

01243 {
01244    /* check minimum length */
01245    if (strlen(password) < minpassword)
01246       return 1;
01247    /* check that password does not contain '*' character */
01248    if (!ast_strlen_zero(password) && password[0] == '*')
01249       return 1;
01250    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01251       char cmd[255], buf[255];
01252 
01253       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01254 
01255       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01256       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01257          ast_debug(5, "Result: %s\n", buf);
01258          if (!strncasecmp(buf, "VALID", 5)) {
01259             ast_debug(3, "Passed password check: '%s'\n", buf);
01260             return 0;
01261          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01262             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01263             return 0;
01264          } else {
01265             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01266             return 1;
01267          }
01268       }
01269    }
01270    return 0;
01271 }

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

Definition at line 7938 of file app_voicemail_imapstorage.c.

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

07939 {
07940    int x = 0;
07941 
07942 #ifndef IMAP_STORAGE
07943    int last_msg_idx;
07944    int res = 0, nummsg;
07945    char fn2[PATH_MAX];
07946 #endif
07947 
07948    if (vms->lastmsg <= -1) {
07949       goto done;
07950    }
07951 
07952    vms->curmsg = -1;
07953 #ifndef IMAP_STORAGE
07954    /* Get the deleted messages fixed */
07955    if (vm_lock_path(vms->curdir)) {
07956       return ERROR_LOCK_PATH;
07957    }
07958 
07959    /* update count as message may have arrived while we've got mailbox open */
07960    last_msg_idx = last_message_index(vmu, vms->curdir);
07961    if (last_msg_idx != vms->lastmsg) {
07962       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
07963    }
07964 
07965    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07966    for (x = 0; x < last_msg_idx + 1; x++) {
07967       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07968          /* Save this message.  It's not in INBOX or hasn't been heard */
07969          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07970          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07971             break;
07972          }
07973          vms->curmsg++;
07974          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
07975          if (strcmp(vms->fn, fn2)) {
07976             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07977          }
07978       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
07979          /* Move to old folder before deleting */
07980          res = save_to_folder(vmu, vms, x, 1);
07981          if (res == ERROR_LOCK_PATH) {
07982             /* If save failed do not delete the message */
07983             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07984             vms->deleted[x] = 0;
07985             vms->heard[x] = 0;
07986             --x;
07987          }
07988       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07989          /* Move to deleted folder */
07990          res = save_to_folder(vmu, vms, x, 10);
07991          if (res == ERROR_LOCK_PATH) {
07992             /* If save failed do not delete the message */
07993             vms->deleted[x] = 0;
07994             vms->heard[x] = 0;
07995             --x;
07996          }
07997       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07998          /* If realtime storage enabled - we should explicitly delete this message,
07999          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
08000          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08001          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08002             DELETE(vms->curdir, x, vms->fn, vmu);
08003          }
08004       }
08005    }
08006 
08007    /* Delete ALL remaining messages */
08008    nummsg = x - 1;
08009    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08010       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08011       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08012          DELETE(vms->curdir, x, vms->fn, vmu);
08013       }
08014    }
08015    ast_unlock_path(vms->curdir);
08016 #else /* defined(IMAP_STORAGE) */
08017    if (vms->deleted) {
08018       /* Since we now expunge after each delete, deleting in reverse order
08019        * ensures that no reordering occurs between each step. */
08020       for (x = vms->dh_arraysize - 1; x >= 0; x--) {
08021          if (vms->deleted[x]) {
08022             ast_debug(3, "IMAP delete of %d\n", x);
08023             DELETE(vms->curdir, x, vms->fn, vmu);
08024          }
08025       }
08026    }
08027 #endif
08028 
08029 done:
08030    if (vms->deleted && vmu->maxmsg) {
08031       memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
08032    }
08033    if (vms->heard && vmu->maxmsg) {
08034       memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
08035    }
08036 
08037    return 0;
08038 }

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

Definition at line 11112 of file app_voicemail_imapstorage.c.

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

11113 {
11114    int which = 0;
11115    int wordlen;
11116    struct ast_vm_user *vmu;
11117    const char *context = "";
11118 
11119    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11120    if (pos > 4)
11121       return NULL;
11122    if (pos == 3)
11123       return (state == 0) ? ast_strdup("for") : NULL;
11124    wordlen = strlen(word);
11125    AST_LIST_TRAVERSE(&users, vmu, list) {
11126       if (!strncasecmp(word, vmu->context, wordlen)) {
11127          if (context && strcmp(context, vmu->context) && ++which > state)
11128             return ast_strdup(vmu->context);
11129          /* ignore repeated contexts ? */
11130          context = vmu->context;
11131       }
11132    }
11133    return NULL;
11134 }

static int copy ( char *  infile,
char *  outfile 
) [static]

Utility function to copy a file.

Parameters:
infile The path to the file to be copied. The file must be readable, it is opened in read only mode.
outfile The 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 4077 of file app_voicemail_imapstorage.c.

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

04078 {
04079    int ifd;
04080    int ofd;
04081    int res;
04082    int len;
04083    char buf[4096];
04084 
04085 #ifdef HARDLINK_WHEN_POSSIBLE
04086    /* Hard link if possible; saves disk space & is faster */
04087    if (link(infile, outfile)) {
04088 #endif
04089       if ((ifd = open(infile, O_RDONLY)) < 0) {
04090          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
04091          return -1;
04092       }
04093       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
04094          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
04095          close(ifd);
04096          return -1;
04097       }
04098       do {
04099          len = read(ifd, buf, sizeof(buf));
04100          if (len < 0) {
04101             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
04102             close(ifd);
04103             close(ofd);
04104             unlink(outfile);
04105          }
04106          if (len) {
04107             res = write(ofd, buf, len);
04108             if (errno == ENOMEM || errno == ENOSPC || res != len) {
04109                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
04110                close(ifd);
04111                close(ofd);
04112                unlink(outfile);
04113             }
04114          }
04115       } while (len);
04116       close(ifd);
04117       close(ofd);
04118       return 0;
04119 #ifdef HARDLINK_WHEN_POSSIBLE
04120    } else {
04121       /* Hard link succeeded */
04122       return 0;
04123    }
04124 #endif
04125 }

static int copy_message ( struct ast_channel chan,
struct ast_vm_user vmu,
int  imbox,
int  msgnum,
long  duration,
struct ast_vm_user recip,
char *  fmt,
char *  dir,
const char *  flag 
) [static]

Copies a message from one mailbox to another.

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

Definition at line 5314 of file app_voicemail_imapstorage.c.

References ast_copy_string(), ast_log(), AST_LOG_ERROR, AST_LOG_NOTICE, ast_strlen_zero(), ast_unlock_path(), ast_channel::caller, ast_vm_user::context, COPY, copy_plain_file(), create_dirpath(), ERROR_LOCK_PATH, EXISTS, ast_party_caller::id, inprocess_count(), ast_channel::language, last_message_index(), ast_vm_user::mailbox, make_dir(), make_file(), maxmsg, mbox(), ast_party_id::name, notify_new_message(), ast_party_id::number, S_COR, STORE, ast_party_name::str, ast_party_number::str, ast_party_name::valid, ast_party_number::valid, vm_delete(), and vm_lock_path().

05315 {
05316    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05317    const char *frombox = mbox(vmu, imbox);
05318    const char *userfolder;
05319    int recipmsgnum;
05320    int res = 0;
05321 
05322    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05323 
05324    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05325       userfolder = "Urgent";
05326    } else {
05327       userfolder = "INBOX";
05328    }
05329 
05330    create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05331 
05332    if (!dir)
05333       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05334    else
05335       ast_copy_string(fromdir, dir, sizeof(fromdir));
05336 
05337    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05338    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder);
05339 
05340    if (vm_lock_path(todir))
05341       return ERROR_LOCK_PATH;
05342 
05343    recipmsgnum = last_message_index(recip, todir) + 1;
05344    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05345       make_file(topath, sizeof(topath), todir, recipmsgnum);
05346 #ifndef ODBC_STORAGE
05347       if (EXISTS(fromdir, msgnum, frompath, chan->language)) { 
05348          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05349       } else {
05350 #endif
05351          /* If we are prepending a message for ODBC, then the message already
05352           * exists in the database, but we want to force copying from the
05353           * filesystem (since only the FS contains the prepend). */
05354          copy_plain_file(frompath, topath);
05355          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05356          vm_delete(topath);
05357 #ifndef ODBC_STORAGE
05358       }
05359 #endif
05360    } else {
05361       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05362       res = -1;
05363    }
05364    ast_unlock_path(todir);
05365    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05366       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05367       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05368       flag);
05369    
05370    return res;
05371 }

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 4136 of file app_voicemail_imapstorage.c.

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

04137 {
04138    char frompath2[PATH_MAX], topath2[PATH_MAX];
04139    struct ast_variable *tmp,*var = NULL;
04140    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04141    ast_filecopy(frompath, topath, NULL);
04142    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04143    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04144    if (ast_check_realtime("voicemail_data")) {
04145       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04146       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04147       for (tmp = var; tmp; tmp = tmp->next) {
04148          if (!strcasecmp(tmp->name, "origmailbox")) {
04149             origmailbox = tmp->value;
04150          } else if (!strcasecmp(tmp->name, "context")) {
04151             context = tmp->value;
04152          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04153             macrocontext = tmp->value;
04154          } else if (!strcasecmp(tmp->name, "exten")) {
04155             exten = tmp->value;
04156          } else if (!strcasecmp(tmp->name, "priority")) {
04157             priority = tmp->value;
04158          } else if (!strcasecmp(tmp->name, "callerchan")) {
04159             callerchan = tmp->value;
04160          } else if (!strcasecmp(tmp->name, "callerid")) {
04161             callerid = tmp->value;
04162          } else if (!strcasecmp(tmp->name, "origdate")) {
04163             origdate = tmp->value;
04164          } else if (!strcasecmp(tmp->name, "origtime")) {
04165             origtime = tmp->value;
04166          } else if (!strcasecmp(tmp->name, "category")) {
04167             category = tmp->value;
04168          } else if (!strcasecmp(tmp->name, "duration")) {
04169             duration = tmp->value;
04170          }
04171       }
04172       ast_store_realtime("voicemail_data", "filename", topath, "origmailbox", origmailbox, "context", context, "macrocontext", macrocontext, "exten", exten, "priority", priority, "callerchan", callerchan, "callerid", callerid, "origdate", origdate, "origtime", origtime, "category", category, "duration", duration, SENTINEL);
04173    }
04174    copy(frompath2, topath2);
04175    ast_variables_destroy(var);
04176 }

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 3972 of file app_voicemail_imapstorage.c.

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

03973 {
03974 
03975    int vmcount = 0;
03976    DIR *vmdir = NULL;
03977    struct dirent *vment = NULL;
03978 
03979    if (vm_lock_path(dir))
03980       return ERROR_LOCK_PATH;
03981 
03982    if ((vmdir = opendir(dir))) {
03983       while ((vment = readdir(vmdir))) {
03984          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03985             vmcount++;
03986          }
03987       }
03988       closedir(vmdir);
03989    }
03990    ast_unlock_path(dir);
03991    
03992    return vmcount;
03993 }

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:
dest String. base directory.
len Length of dest.
context String. Ignored if is null or empty string.
ext String. Ignored if is null or empty string.
folder String. Ignored if is null or empty string.
Returns:
-1 on failure, 0 on success.

Definition at line 1689 of file app_voicemail_imapstorage.c.

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

01690 {
01691    mode_t   mode = VOICEMAIL_DIR_MODE;
01692    int res;
01693 
01694    make_dir(dest, len, context, ext, folder);
01695    if ((res = ast_mkdir(dest, mode))) {
01696       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01697       return -1;
01698    }
01699    return 0;
01700 }

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

Definition at line 13118 of file app_voicemail_imapstorage.c.

References ast_copy_string(), ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_suite_event_notify, ast_verb, ast_verbose, ast_waitfordigit(), ast_channel::context, ast_channel::exten, option_verbose, ast_channel::priority, and VERBOSE_PREFIX_3.

13119 {
13120    int cmd = 0;
13121    char destination[80] = "";
13122    int retries = 0;
13123 
13124    if (!num) {
13125       ast_verb(3, "Destination number will be entered manually\n");
13126       while (retries < 3 && cmd != 't') {
13127          destination[1] = '\0';
13128          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13129          if (!cmd)
13130             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13131          if (!cmd)
13132             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13133          if (!cmd) {
13134             cmd = ast_waitfordigit(chan, 6000);
13135             if (cmd)
13136                destination[0] = cmd;
13137          }
13138          if (!cmd) {
13139             retries++;
13140          } else {
13141 
13142             if (cmd < 0)
13143                return 0;
13144             if (cmd == '*') {
13145                ast_verb(3, "User hit '*' to cancel outgoing call\n");
13146                return 0;
13147             }
13148             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
13149                retries++;
13150             else
13151                cmd = 't';
13152          }
13153          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13154       }
13155       if (retries >= 3) {
13156          return 0;
13157       }
13158       
13159    } else {
13160       if (option_verbose > 2)
13161          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
13162       ast_copy_string(destination, num, sizeof(destination));
13163    }
13164 
13165    if (!ast_strlen_zero(destination)) {
13166       if (destination[strlen(destination) -1 ] == '*')
13167          return 0; 
13168       if (option_verbose > 2)
13169          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13170       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13171       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13172       chan->priority = 0;
13173       return 9;
13174    }
13175    return 0;
13176 }

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

Definition at line 10695 of file app_voicemail_imapstorage.c.

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

10696 {
10697    struct ast_vm_user *vmu;
10698 
10699    if (!ast_strlen_zero(box) && box[0] == '*') {
10700       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
10701             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10702             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
10703             "\n\tand will be ignored.\n", box, context);
10704       return NULL;
10705    }
10706 
10707    AST_LIST_TRAVERSE(&users, vmu, list) {
10708       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10709          if (strcasecmp(vmu->context, context)) {
10710             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10711                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10712                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10713                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10714          }
10715          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10716          return NULL;
10717       }
10718       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10719          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10720          return NULL;
10721       }
10722    }
10723    
10724    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10725       return NULL;
10726    
10727    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10728    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10729 
10730    AST_LIST_INSERT_TAIL(&users, vmu, list);
10731    
10732    return vmu;
10733 }

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 1441 of file app_voicemail_imapstorage.c.

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

01442 {
01443    /* This function could be made to generate one from a database, too */
01444    struct ast_vm_user *vmu = NULL, *cur;
01445    AST_LIST_LOCK(&users);
01446 
01447    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01448       context = "default";
01449 
01450    AST_LIST_TRAVERSE(&users, cur, list) {
01451 #ifdef IMAP_STORAGE
01452       if (cur->imapversion != imapversion) {
01453          continue;
01454       }
01455 #endif
01456       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01457          break;
01458       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01459          break;
01460    }
01461    if (cur) {
01462       /* Make a copy, so that on a reload, we have no race */
01463       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01464          *vmu = *cur;
01465          if (!ivm) {
01466             vmu->emailbody = ast_strdup(cur->emailbody);
01467             vmu->emailsubject = ast_strdup(cur->emailsubject);
01468          }
01469          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01470          AST_LIST_NEXT(vmu, list) = NULL;
01471       }
01472    } else
01473       vmu = find_user_realtime(ivm, context, mailbox);
01474    AST_LIST_UNLOCK(&users);
01475    return vmu;
01476 }

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 1404 of file app_voicemail_imapstorage.c.

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

01405 {
01406    struct ast_variable *var;
01407    struct ast_vm_user *retval;
01408 
01409    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01410       if (!ivm)
01411          ast_set_flag(retval, VM_ALLOCED);   
01412       else
01413          memset(retval, 0, sizeof(*retval));
01414       if (mailbox) 
01415          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01416       populate_defaults(retval);
01417       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01418          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01419       else
01420          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01421       if (var) {
01422          apply_options_full(retval, var);
01423          ast_variables_destroy(var);
01424       } else { 
01425          if (!ivm) 
01426             free_user(retval);
01427          retval = NULL;
01428       }  
01429    } 
01430    return retval;
01431 }

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_message Used 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):

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

Returns:
zero on success, -1 on error.

Definition at line 7143 of file app_voicemail_imapstorage.c.

References ast_clear_flag, ast_copy_string(), ast_fileexists(), ast_filerename(), AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_LOG_ERROR, AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_say_digit_str(), ast_stream_and_wait(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_waitfordigit(), ast_channel::caller, ast_vm_user::context, ast_channel::context, copy_message(), vm_state::curbox, vm_state::curdir, vm_state::curmsg, DISPOSE, ast_channel::exten, find_user(), free_user(), globalflags, ast_party_caller::id, inboxcount(), inprocess_count(), ast_channel::language, leave_voicemail(), ast_app::list, LOG_ERROR, LOG_NOTICE, ast_vm_user::mailbox, make_file(), ast_vm_user::maxmsg, ast_party_id::name, ast_party_id::number, pbx_exec(), pbx_findapp(), ast_channel::priority, RETRIEVE, run_externnotify(), S_COR, S_OR, sendmail(), serveremail, STORE, ast_party_name::str, ast_party_number::str, strsep(), vm_state::username, ast_party_name::valid, ast_party_number::valid, VM_ATTACH, VM_DIRECFORWARD, vm_forwardoptions(), VM_FWDURGAUTO, VM_SPOOL_DIR, and vmfmts.

07144 {
07145 #ifdef IMAP_STORAGE
07146    int todircount = 0;
07147    struct vm_state *dstvms;
07148 #endif
07149    char username[70]="";
07150    char fn[PATH_MAX]; /* for playback of name greeting */
07151    char ecodes[16] = "#";
07152    int res = 0, cmd = 0;
07153    struct ast_vm_user *receiver = NULL, *vmtmp;
07154    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
07155    char *stringp;
07156    const char *s;
07157    int saved_messages = 0;
07158    int valid_extensions = 0;
07159    char *dir;
07160    int curmsg;
07161    char urgent_str[7] = "";
07162    int prompt_played = 0;
07163 #ifndef IMAP_STORAGE
07164    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
07165 #endif
07166    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
07167       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
07168    }
07169 
07170    if (vms == NULL) return -1;
07171    dir = vms->curdir;
07172    curmsg = vms->curmsg;
07173 
07174    ast_test_suite_event_notify("FORWARD", "Message: entering forward message menu");
07175    while (!res && !valid_extensions) {
07176       int use_directory = 0;
07177       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
07178          int done = 0;
07179          int retries = 0;
07180          cmd = 0;
07181          while ((cmd >= 0) && !done ){
07182             if (cmd)
07183                retries = 0;
07184             switch (cmd) {
07185             case '1': 
07186                use_directory = 0;
07187                done = 1;
07188                break;
07189             case '2': 
07190                use_directory = 1;
07191                done = 1;
07192                break;
07193             case '*': 
07194                cmd = 't';
07195                done = 1;
07196                break;
07197             default: 
07198                /* Press 1 to enter an extension press 2 to use the directory */
07199                cmd = ast_play_and_wait(chan, "vm-forward");
07200                if (!cmd) {
07201                   cmd = ast_waitfordigit(chan, 3000);
07202                }
07203                if (!cmd) {
07204                   retries++;
07205                }
07206                if (retries > 3) {
07207                   cmd = 't';
07208                   done = 1;
07209                }
07210                ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
07211             }
07212          }
07213          if (cmd < 0 || cmd == 't')
07214             break;
07215       }
07216       
07217       if (use_directory) {
07218          /* use app_directory */
07219          
07220          char old_context[sizeof(chan->context)];
07221          char old_exten[sizeof(chan->exten)];
07222          int old_priority;
07223          struct ast_app* directory_app;
07224 
07225          directory_app = pbx_findapp("Directory");
07226          if (directory_app) {
07227             char vmcontext[256];
07228             /* make backup copies */
07229             memcpy(old_context, chan->context, sizeof(chan->context));
07230             memcpy(old_exten, chan->exten, sizeof(chan->exten));
07231             old_priority = chan->priority;
07232             
07233             /* call the the Directory, changes the channel */
07234             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
07235             res = pbx_exec(chan, directory_app, vmcontext);
07236             
07237             ast_copy_string(username, chan->exten, sizeof(username));
07238             
07239             /* restore the old context, exten, and priority */
07240             memcpy(chan->context, old_context, sizeof(chan->context));
07241             memcpy(chan->exten, old_exten, sizeof(chan->exten));
07242             chan->priority = old_priority;
07243          } else {
07244             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
07245             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
07246          }
07247       } else {
07248          /* Ask for an extension */
07249          ast_test_suite_event_notify("PLAYBACK", "Message: vm-extension");
07250          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
07251          prompt_played++;
07252          if (res || prompt_played > 4)
07253             break;
07254          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
07255             break;
07256       }
07257       
07258       /* start all over if no username */
07259       if (ast_strlen_zero(username))
07260          continue;
07261       stringp = username;
07262       s = strsep(&stringp, "*");
07263       /* start optimistic */
07264       valid_extensions = 1;
07265       while (s) {
07266          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
07267             int oldmsgs;
07268             int newmsgs;
07269             int capacity;
07270             if (inboxcount(s, &newmsgs, &oldmsgs)) {
07271                ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
07272                /* Shouldn't happen, but allow trying another extension if it does */
07273                res = ast_play_and_wait(chan, "pbx-invalid");
07274                valid_extensions = 0;
07275                break;
07276             }
07277             capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
07278             if ((newmsgs + oldmsgs) >= capacity) {
07279                ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
07280                res = ast_play_and_wait(chan, "vm-mailboxfull");
07281                valid_extensions = 0;
07282                while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07283                   inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07284                   free_user(vmtmp);
07285                }
07286                inprocess_count(receiver->mailbox, receiver->context, -1);
07287                break;
07288             }
07289             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
07290          } else {
07291             /* XXX Optimization for the future.  When we encounter a single bad extension,
07292              * bailing out on all of the extensions may not be the way to go.  We should
07293              * probably just bail on that single extension, then allow the user to enter
07294              * several more. XXX
07295              */
07296             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07297                free_user(receiver);
07298             }
07299             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
07300             /* "I am sorry, that's not a valid extension.  Please try again." */
07301             res = ast_play_and_wait(chan, "pbx-invalid");
07302             valid_extensions = 0;
07303             break;
07304          }
07305 
07306          /* play name if available, else play extension number */
07307          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
07308          RETRIEVE(fn, -1, s, receiver->context);
07309          if (ast_fileexists(fn, NULL, NULL) > 0) {
07310             res = ast_stream_and_wait(chan, fn, ecodes);
07311             if (res) {
07312                DISPOSE(fn, -1);
07313                return res;
07314             }
07315          } else {
07316             res = ast_say_digit_str(chan, s, ecodes, chan->language);
07317          }
07318          DISPOSE(fn, -1);
07319 
07320          s = strsep(&stringp, "*");
07321       }
07322       /* break from the loop of reading the extensions */
07323       if (valid_extensions)
07324          break;
07325    }
07326    /* check if we're clear to proceed */
07327    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
07328       return res;
07329    if (is_new_message == 1) {
07330       struct leave_vm_options leave_options;
07331       char mailbox[AST_MAX_EXTENSION * 2 + 2];
07332       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
07333 
07334       /* Send VoiceMail */
07335       memset(&leave_options, 0, sizeof(leave_options));
07336       leave_options.record_gain = record_gain;
07337       cmd = leave_voicemail(chan, mailbox, &leave_options);
07338    } else {
07339       /* Forward VoiceMail */
07340       long duration = 0;
07341       struct vm_state vmstmp;
07342       int copy_msg_result = 0;
07343       memcpy(&vmstmp, vms, sizeof(vmstmp));
07344 
07345       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
07346 
07347       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
07348       if (!cmd) {
07349          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
07350 #ifdef IMAP_STORAGE
07351             int attach_user_voicemail;
07352             char *myserveremail = serveremail;
07353             
07354             /* get destination mailbox */
07355             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
07356             if (!dstvms) {
07357                dstvms = create_vm_state_from_user(vmtmp);
07358             }
07359             if (dstvms) {
07360                init_mailstream(dstvms, 0);
07361                if (!dstvms->mailstream) {
07362                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
07363                } else {
07364                   copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
07365                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
07366                }
07367             } else {
07368                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
07369             }
07370             if (!ast_strlen_zero(vmtmp->serveremail))
07371                myserveremail = vmtmp->serveremail;
07372             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
07373             /* NULL category for IMAP storage */
07374             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
07375                dstvms->curbox,
07376                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
07377                S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
07378                vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
07379                NULL, urgent_str);
07380 #else
07381             copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
07382 #endif
07383             saved_messages++;
07384             AST_LIST_REMOVE_CURRENT(list);
07385             inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07386             free_user(vmtmp);
07387             if (res)
07388                break;
07389          }
07390          AST_LIST_TRAVERSE_SAFE_END;
07391          if (saved_messages > 0 && !copy_msg_result) {
07392             /* give confirmation that the message was saved */
07393             /* commented out since we can't forward batches yet
07394             if (saved_messages == 1)
07395                res = ast_play_and_wait(chan, "vm-message");
07396             else
07397                res = ast_play_and_wait(chan, "vm-messages");
07398             if (!res)
07399                res = ast_play_and_wait(chan, "vm-saved"); */
07400 #ifdef IMAP_STORAGE
07401             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
07402             if (ast_strlen_zero(vmstmp.introfn))
07403 #endif
07404             res = ast_play_and_wait(chan, "vm-msgsaved");
07405          }
07406 #ifndef IMAP_STORAGE
07407          else {
07408             /* with IMAP, mailbox full warning played by imap_check_limits */
07409             res = ast_play_and_wait(chan, "vm-mailboxfull");
07410          }
07411          /* Restore original message without prepended message if backup exists */
07412          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07413          strcpy(textfile, msgfile);
07414          strcpy(backup, msgfile);
07415          strcpy(backup_textfile, msgfile);
07416          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07417          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
07418          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07419          if (ast_fileexists(backup, NULL, NULL) > 0) {
07420             ast_filerename(backup, msgfile, NULL);
07421             rename(backup_textfile, textfile);
07422          }
07423 #endif
07424       }
07425       DISPOSE(dir, curmsg);
07426 #ifndef IMAP_STORAGE
07427       if (cmd) { /* assuming hangup, cleanup backup file */
07428          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07429          strcpy(textfile, msgfile);
07430          strcpy(backup_textfile, msgfile);
07431          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07432          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07433          rename(backup_textfile, textfile);
07434       }
07435 #endif
07436    }
07437 
07438    /* If anything failed above, we still have this list to free */
07439    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07440       inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07441       free_user(vmtmp);
07442    }
07443    return res ? res : cmd;
07444 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1744 of file app_voicemail_imapstorage.c.

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

01745 {
01746    if (ast_test_flag(vmu, VM_ALLOCED)) {
01747 
01748       ast_free(vmu->emailbody);
01749       vmu->emailbody = NULL;
01750 
01751       ast_free(vmu->emailsubject);
01752       vmu->emailsubject = NULL;
01753 
01754       ast_free(vmu);
01755    }
01756 }

static void free_vm_users ( void   )  [static]

Free the users structure.

Definition at line 11711 of file app_voicemail_imapstorage.c.

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

11712 {
11713    struct ast_vm_user *current;
11714    AST_LIST_LOCK(&users);
11715    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11716       ast_set_flag(current, VM_ALLOCED);
11717       free_user(current);
11718    }
11719    AST_LIST_UNLOCK(&users);
11720 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11723 of file app_voicemail_imapstorage.c.

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

11724 {
11725    struct vm_zone *zcur;
11726    AST_LIST_LOCK(&zones);
11727    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11728       free_zone(zcur);
11729    AST_LIST_UNLOCK(&zones);
11730 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5082 of file app_voicemail_imapstorage.c.

References ast_free.

05083 {
05084    ast_free(z);
05085 }

static int get_date ( char *  s,
int  len 
) [static]

Gets the current date and time, as formatted string.

Parameters:
s The buffer to hold the output formatted date.
len the 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 5038 of file app_voicemail_imapstorage.c.

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

05039 {
05040    struct ast_tm tm;
05041    struct timeval t = ast_tvnow();
05042    
05043    ast_localtime(&t, &tm, "UTC");
05044 
05045    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05046 }

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 6755 of file app_voicemail_imapstorage.c.

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

06756 {
06757    int x;
06758    int d;
06759    char fn[PATH_MAX];
06760    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06761    if (d)
06762       return d;
06763    for (x = start; x < 5; x++) { /* For all folders */
06764       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06765          return d;
06766       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06767       if (d)
06768          return d;
06769       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06770 
06771       /* The inbox folder can have its name changed under certain conditions
06772        * so this checks if the sound file exists for the inbox folder name and
06773        * if it doesn't, plays the default name instead. */
06774       if (x == 0) {
06775          if (ast_fileexists(fn, NULL, NULL)) {
06776             d = vm_play_folder_name(chan, fn);
06777          } else {
06778             ast_verb(1, "failed to find %s\n", fn);
06779             d = vm_play_folder_name(chan, "vm-INBOX");
06780          }
06781       } else {
06782          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06783          d = vm_play_folder_name(chan, fn);
06784       }
06785 
06786       if (d)
06787          return d;
06788       d = ast_waitfordigit(chan, 500);
06789       if (d)
06790          return d;
06791    }
06792 
06793    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06794    if (d)
06795       return d;
06796    d = ast_waitfordigit(chan, 4000);
06797    return d;
06798 }

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

plays a prompt and waits for a keypress.

Parameters:
chan 
fn the name of the voice prompt file to be played. For example, 'vm-changeto', 'vm-savefolder'
start Does 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 6812 of file app_voicemail_imapstorage.c.

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

06813 {
06814    int res = 0;
06815    int loops = 0;
06816 
06817    res = ast_play_and_wait(chan, fn);  /* Folder name */
06818    while (((res < '0') || (res > '9')) &&
06819          (res != '#') && (res >= 0) &&
06820          loops < 4) {
06821       res = get_folder(chan, 0);
06822       loops++;
06823    }
06824    if (loops == 4) { /* give up */
06825       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06826       return '#';
06827    }
06828    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06829    return res;
06830 }

static int get_folder_by_name ( const char *  name  )  [static]

Definition at line 1731 of file app_voicemail_imapstorage.c.

References ARRAY_LEN.

01732 {
01733    size_t i;
01734 
01735    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01736       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01737          return i;
01738       }
01739    }
01740 
01741    return -1;
01742 }

static int handle_subscribe ( void *  datap  )  [static]

Definition at line 11494 of file app_voicemail_imapstorage.c.

References ast_calloc, ast_free, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), mwi_sub_task::context, mwi_sub_task::mailbox, mwi_sub, poll_subscribed_mailbox(), mwi_sub_task::uniqueid, and ast_event_sub::uniqueid.

11495 {
11496    unsigned int len;
11497    struct mwi_sub *mwi_sub;
11498    struct mwi_sub_task *p = datap;
11499 
11500    len = sizeof(*mwi_sub);
11501    if (!ast_strlen_zero(p->mailbox))
11502       len += strlen(p->mailbox);
11503 
11504    if (!ast_strlen_zero(p->context))
11505       len += strlen(p->context) + 1; /* Allow for seperator */
11506 
11507    if (!(mwi_sub = ast_calloc(1, len)))
11508       return -1;
11509 
11510    mwi_sub->uniqueid = p->uniqueid;
11511    if (!ast_strlen_zero(p->mailbox))
11512       strcpy(mwi_sub->mailbox, p->mailbox);
11513 
11514    if (!ast_strlen_zero(p->context)) {
11515       strcat(mwi_sub->mailbox, "@");
11516       strcat(mwi_sub->mailbox, p->context);
11517    }
11518 
11519    AST_RWLIST_WRLOCK(&mwi_subs);
11520    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11521    AST_RWLIST_UNLOCK(&mwi_subs);
11522    ast_free((void *) p->mailbox);
11523    ast_free((void *) p->context);
11524    ast_free(p);
11525    poll_subscribed_mailbox(mwi_sub);
11526    return 0;
11527 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11472 of file app_voicemail_imapstorage.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, mwi_sub::entry, mwi_sub, mwi_sub_destroy(), ast_event_sub::uniqueid, and mwi_sub::uniqueid.

11473 {
11474    struct mwi_sub *mwi_sub;
11475    uint32_t *uniqueid = datap;
11476    
11477    AST_RWLIST_WRLOCK(&mwi_subs);
11478    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11479       if (mwi_sub->uniqueid == *uniqueid) {
11480          AST_LIST_REMOVE_CURRENT(entry);
11481          break;
11482       }
11483    }
11484    AST_RWLIST_TRAVERSE_SAFE_END
11485    AST_RWLIST_UNLOCK(&mwi_subs);
11486 
11487    if (mwi_sub)
11488       mwi_sub_destroy(mwi_sub);
11489 
11490    ast_free(uniqueid);  
11491    return 0;
11492 }

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 11247 of file app_voicemail_imapstorage.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, load_config(), and ast_cli_entry::usage.

11248 {
11249    switch (cmd) {
11250    case CLI_INIT:
11251       e->command = "voicemail reload";
11252       e->usage =
11253          "Usage: voicemail reload\n"
11254          "       Reload voicemail configuration\n";
11255       return NULL;
11256    case CLI_GENERATE:
11257       return NULL;
11258    }
11259 
11260    if (a->argc != 2)
11261       return CLI_SHOWUSAGE;
11262 
11263    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11264    load_config(1);
11265    
11266    return CLI_SUCCESS;
11267 }

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 11137 of file app_voicemail_imapstorage.c.

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

11138 {
11139    struct ast_vm_user *vmu;
11140 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11141    const char *context = NULL;
11142    int users_counter = 0;
11143 
11144    switch (cmd) {
11145    case CLI_INIT:
11146       e->command = "voicemail show users";
11147       e->usage =
11148          "Usage: voicemail show users [for <context>]\n"
11149          "       Lists all mailboxes currently set up\n";
11150       return NULL;
11151    case CLI_GENERATE:
11152       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
11153    }  
11154 
11155    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
11156       return CLI_SHOWUSAGE;
11157    if (a->argc == 5) {
11158       if (strcmp(a->argv[3],"for"))
11159          return CLI_SHOWUSAGE;
11160       context = a->argv[4];
11161    }
11162 
11163    if (ast_check_realtime("voicemail")) {
11164       if (!context) {
11165          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
11166          return CLI_SHOWUSAGE;
11167       }
11168       return show_users_realtime(a->fd, context);
11169    }
11170 
11171    AST_LIST_LOCK(&users);
11172    if (AST_LIST_EMPTY(&users)) {
11173       ast_cli(a->fd, "There are no voicemail users currently defined\n");
11174       AST_LIST_UNLOCK(&users);
11175       return CLI_FAILURE;
11176    }
11177    if (a->argc == 3)
11178       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11179    else {
11180       int count = 0;
11181       AST_LIST_TRAVERSE(&users, vmu, list) {
11182          if (!strcmp(context, vmu->context))
11183             count++;
11184       }
11185       if (count) {
11186          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11187       } else {
11188          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
11189          AST_LIST_UNLOCK(&users);
11190          return CLI_FAILURE;
11191       }
11192    }
11193    AST_LIST_TRAVERSE(&users, vmu, list) {
11194       int newmsgs = 0, oldmsgs = 0;
11195       char count[12], tmp[256] = "";
11196 
11197       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
11198          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
11199          inboxcount(tmp, &newmsgs, &oldmsgs);
11200          snprintf(count, sizeof(count), "%d", newmsgs);
11201          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
11202          users_counter++;
11203       }
11204    }
11205    AST_LIST_UNLOCK(&users);
11206    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
11207    return CLI_SUCCESS;
11208 }

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 11211 of file app_voicemail_imapstorage.c.

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

11212 {
11213    struct vm_zone *zone;
11214 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11215    char *res = CLI_SUCCESS;
11216 
11217    switch (cmd) {
11218    case CLI_INIT:
11219       e->command = "voicemail show zones";
11220       e->usage =
11221          "Usage: voicemail show zones\n"
11222          "       Lists zone message formats\n";
11223       return NULL;
11224    case CLI_GENERATE:
11225       return NULL;
11226    }
11227 
11228    if (a->argc != 3)
11229       return CLI_SHOWUSAGE;
11230 
11231    AST_LIST_LOCK(&zones);
11232    if (!AST_LIST_EMPTY(&zones)) {
11233       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11234       AST_LIST_TRAVERSE(&zones, zone, list) {
11235          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11236       }
11237    } else {
11238       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11239       res = CLI_FAILURE;
11240    }
11241    AST_LIST_UNLOCK(&zones);
11242 
11243    return res;
11244 }

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

Determines if the given folder has messages.

Parameters:
mailbox The @ delimited string for user. If no context is found, uses 'default' for the context.
folder the 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 5426 of file app_voicemail_imapstorage.c.

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

05427 {
05428    char tmp[256], *tmp2 = tmp, *box, *context;
05429    ast_copy_string(tmp, mailbox, sizeof(tmp));
05430    if (ast_strlen_zero(folder)) {
05431       folder = "INBOX";
05432    }
05433    while ((box = strsep(&tmp2, ",&"))) {
05434       if ((context = strchr(box, '@')))
05435          *context++ = '\0';
05436       else
05437          context = "default";
05438       if (__has_voicemail(context, box, folder, 1))
05439          return 1;
05440       /* If we are checking INBOX, we should check Urgent as well */
05441       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05442          return 1;
05443       }
05444    }
05445    return 0;
05446 }

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

Definition at line 5508 of file app_voicemail_imapstorage.c.

References inboxcount2().

05509 {
05510    int urgentmsgs = 0;
05511    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05512    if (newmsgs) {
05513       *newmsgs += urgentmsgs;
05514    }
05515    return res;
05516 }

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

Definition at line 5449 of file app_voicemail_imapstorage.c.

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

05450 {
05451    char tmp[256];
05452    char *context;
05453 
05454    /* If no mailbox, return immediately */
05455    if (ast_strlen_zero(mailbox))
05456       return 0;
05457 
05458    if (newmsgs)
05459       *newmsgs = 0;
05460    if (oldmsgs)
05461       *oldmsgs = 0;
05462    if (urgentmsgs)
05463       *urgentmsgs = 0;
05464 
05465    if (strchr(mailbox, ',')) {
05466       int tmpnew, tmpold, tmpurgent;
05467       char *mb, *cur;
05468 
05469       ast_copy_string(tmp, mailbox, sizeof(tmp));
05470       mb = tmp;
05471       while ((cur = strsep(&mb, ", "))) {
05472          if (!ast_strlen_zero(cur)) {
05473             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05474                return -1;
05475             else {
05476                if (newmsgs)
05477                   *newmsgs += tmpnew; 
05478                if (oldmsgs)
05479                   *oldmsgs += tmpold;
05480                if (urgentmsgs)
05481                   *urgentmsgs += tmpurgent;
05482             }
05483          }
05484       }
05485       return 0;
05486    }
05487 
05488    ast_copy_string(tmp, mailbox, sizeof(tmp));
05489    
05490    if ((context = strchr(tmp, '@')))
05491       *context++ = '\0';
05492    else
05493       context = "default";
05494 
05495    if (newmsgs)
05496       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05497    if (oldmsgs)
05498       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05499    if (urgentmsgs)
05500       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05501 
05502    return 0;
05503 }

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

utility used by inchar(), for base_encode()

Definition at line 4208 of file app_voicemail_imapstorage.c.

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

04209 {
04210    int l;
04211 
04212    if (bio->ateof)
04213       return 0;
04214 
04215    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04216       if (ferror(fi))
04217          return -1;
04218 
04219       bio->ateof = 1;
04220       return 0;
04221    }
04222 
04223    bio->iolen = l;
04224    bio->iocp = 0;
04225 
04226    return 1;
04227 }

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

utility used by base_encode()

Definition at line 4232 of file app_voicemail_imapstorage.c.

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

04233 {
04234    if (bio->iocp>=bio->iolen) {
04235       if (!inbuf(bio, fi))
04236          return EOF;
04237    }
04238 
04239    return bio->iobuf[bio->iocp++];
04240 }

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

Definition at line 943 of file app_voicemail_imapstorage.c.

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

00944 {
00945    struct inprocess *i = obj, *j = arg;
00946    if (strcmp(i->mailbox, j->mailbox)) {
00947       return 0;
00948    }
00949    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00950 }

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

Definition at line 952 of file app_voicemail_imapstorage.c.

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

00953 {
00954    struct inprocess *i, *arg = alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00955    arg->context = arg->mailbox + strlen(mailbox) + 1;
00956    strcpy(arg->mailbox, mailbox); /* SAFE */
00957    strcpy(arg->context, context); /* SAFE */
00958    ao2_lock(inprocess_container);
00959    if ((i = ao2_find(inprocess_container, arg, 0))) {
00960       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00961       ao2_unlock(inprocess_container);
00962       ao2_ref(i, -1);
00963       return ret;
00964    }
00965    if (delta < 0) {
00966       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
00967    }
00968    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00969       ao2_unlock(inprocess_container);
00970       return 0;
00971    }
00972    i->context = i->mailbox + strlen(mailbox) + 1;
00973    strcpy(i->mailbox, mailbox); /* SAFE */
00974    strcpy(i->context, context); /* SAFE */
00975    i->count = delta;
00976    ao2_link(inprocess_container, i);
00977    ao2_unlock(inprocess_container);
00978    ao2_ref(i, -1);
00979    return 0;
00980 }

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

Definition at line 937 of file app_voicemail_imapstorage.c.

References inprocess::mailbox.

00938 {
00939    const struct inprocess *i = obj;
00940    return atoi(i->mailbox);
00941 }

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

Definition at line 5048 of file app_voicemail_imapstorage.c.

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

05049 {
05050    int res;
05051    char fn[PATH_MAX];
05052    char dest[PATH_MAX];
05053 
05054    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
05055 
05056    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
05057       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
05058       return -1;
05059    }
05060 
05061    RETRIEVE(fn, -1, ext, context);
05062    if (ast_fileexists(fn, NULL, NULL) > 0) {
05063       res = ast_stream_and_wait(chan, fn, ecodes);
05064       if (res) {
05065          DISPOSE(fn, -1);
05066          return res;
05067       }
05068    } else {
05069       /* Dispose just in case */
05070       DISPOSE(fn, -1);
05071       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
05072       if (res)
05073          return res;
05074       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
05075       if (res)
05076          return res;
05077    }
05078    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
05079    return res;
05080 }

static int is_valid_dtmf ( const char *  key  )  [static]

Determines if a DTMF key entered is valid.

Parameters:
key The 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 1379 of file app_voicemail_imapstorage.c.

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

01380 {
01381    int i;
01382    char *local_key = ast_strdupa(key);
01383 
01384    for (i = 0; i < strlen(key); ++i) {
01385       if (!strchr(VALID_DTMF, *local_key)) {
01386          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01387          return 0;
01388       }
01389       local_key++;
01390    }
01391    return 1;
01392 }

static int last_message_index ( struct ast_vm_user vmu,
char *  dir 
) [static]

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

Parameters:
vmu 
dir the 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 4026 of file app_voicemail_imapstorage.c.

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

04027 {
04028    int x;
04029    unsigned char map[MAXMSGLIMIT] = "";
04030    DIR *msgdir;
04031    struct dirent *msgdirent;
04032    int msgdirint;
04033    char extension[4];
04034    int stopcount = 0;
04035 
04036    /* Reading the entire directory into a file map scales better than
04037     * doing a stat repeatedly on a predicted sequence.  I suspect this
04038     * is partially due to stat(2) internally doing a readdir(2) itself to
04039     * find each file. */
04040    if (!(msgdir = opendir(dir))) {
04041       return -1;
04042    }
04043 
04044    while ((msgdirent = readdir(msgdir))) {
04045       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
04046          map[msgdirint] = 1;
04047          stopcount++;
04048          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
04049       }
04050    }
04051    closedir(msgdir);
04052 
04053    for (x = 0; x < vmu->maxmsg; x++) {
04054       if (map[x] == 1) {
04055          stopcount--;
04056       } else if (map[x] == 0 && !stopcount) {
04057          break;
04058       }
04059    }
04060 
04061    return x - 1;
04062 }

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 
options OPT_BUSY_GREETING, OPT_UNAVAIL_GREETING
Returns:
zero on success, -1 on error.

Definition at line 5581 of file app_voicemail_imapstorage.c.

References ast_canmatch_extension(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_exists_extension(), ast_fileexists(), ast_free, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::caller, ast_channel::context, ast_vm_user::context, create_dirpath(), DISPOSE, errno, ast_vm_user::exit, find_user(), ast_party_caller::id, LOG_WARNING, ast_channel::macrocontext, ast_vm_user::mailbox, ast_party_id::number, OPT_BUSY_GREETING, OPT_DTMFEXIT, OPT_MESSAGE_PRIORITY, OPT_MESSAGE_Urgent, OPT_UNAVAIL_GREETING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), RETRIEVE, S_COR, ast_party_number::str, ast_party_number::valid, VM_OPERATOR, VM_SPOOL_DIR, and VOICEMAIL_DIR_MODE.

05582 {
05583 #ifdef IMAP_STORAGE
05584    int newmsgs, oldmsgs;
05585 #else
05586    char urgdir[PATH_MAX];
05587 #endif
05588    char txtfile[PATH_MAX];
05589    char tmptxtfile[PATH_MAX];
05590    struct vm_state *vms = NULL;
05591    char callerid[256];
05592    FILE *txt;
05593    char date[256];
05594    int txtdes;
05595    int res = 0;
05596    int msgnum;
05597    int duration = 0;
05598    int sound_duration = 0;
05599    int ausemacro = 0;
05600    int ousemacro = 0;
05601    int ouseexten = 0;
05602    char tmpdur[16];
05603    char priority[16];
05604    char origtime[16];
05605    char dir[PATH_MAX];
05606    char tmpdir[PATH_MAX];
05607    char fn[PATH_MAX];
05608    char prefile[PATH_MAX] = "";
05609    char tempfile[PATH_MAX] = "";
05610    char ext_context[256] = "";
05611    char fmt[80];
05612    char *context;
05613    char ecodes[17] = "#";
05614    struct ast_str *tmp = ast_str_create(16);
05615    char *tmpptr;
05616    struct ast_vm_user *vmu;
05617    struct ast_vm_user svm;
05618    const char *category = NULL;
05619    const char *code;
05620    const char *alldtmf = "0123456789ABCD*#";
05621    char flag[80];
05622 
05623    if (!tmp) {
05624       return -1;
05625    }
05626 
05627    ast_str_set(&tmp, 0, "%s", ext);
05628    ext = ast_str_buffer(tmp);
05629    if ((context = strchr(ext, '@'))) {
05630       *context++ = '\0';
05631       tmpptr = strchr(context, '&');
05632    } else {
05633       tmpptr = strchr(ext, '&');
05634    }
05635 
05636    if (tmpptr)
05637       *tmpptr++ = '\0';
05638 
05639    ast_channel_lock(chan);
05640    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
05641       category = ast_strdupa(category);
05642    }
05643    ast_channel_unlock(chan);
05644 
05645    if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
05646       ast_copy_string(flag, "Urgent", sizeof(flag));
05647    } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
05648       ast_copy_string(flag, "PRIORITY", sizeof(flag));
05649    } else {
05650       flag[0] = '\0';
05651    }
05652 
05653    ast_debug(3, "Before find_user\n");
05654    if (!(vmu = find_user(&svm, context, ext))) {
05655       ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
05656       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05657       ast_free(tmp);
05658       return res;
05659    }
05660    /* Setup pre-file if appropriate */
05661    if (strcmp(vmu->context, "default"))
05662       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
05663    else
05664       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
05665 
05666    /* Set the path to the prefile. Will be one of 
05667       VM_SPOOL_DIRcontext/ext/busy
05668       VM_SPOOL_DIRcontext/ext/unavail
05669       Depending on the flag set in options.
05670    */
05671    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
05672       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
05673    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
05674       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
05675    }
05676    /* Set the path to the tmpfile as
05677       VM_SPOOL_DIR/context/ext/temp
05678       and attempt to create the folder structure.
05679    */
05680    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
05681    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
05682       ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
05683       ast_free(tmp);
05684       return -1;
05685    }
05686    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
05687    if (ast_fileexists(tempfile, NULL, NULL) > 0)
05688       ast_copy_string(prefile, tempfile, sizeof(prefile));
05689 
05690    DISPOSE(tempfile, -1);
05691    /* It's easier just to try to make it than to check for its existence */
05692 #ifndef IMAP_STORAGE
05693    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
05694 #else
05695    snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
05696    if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
05697       ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
05698    }
05699 #endif
05700 
05701    /* Check current or macro-calling context for special extensions */
05702    if (ast_test_flag(vmu, VM_OPERATOR)) {
05703       if (!ast_strlen_zero(vmu->exit)) {
05704          if (ast_exists_extension(chan, vmu->exit, "o", 1,
05705             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05706             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05707             ouseexten = 1;
05708          }
05709       } else if (ast_exists_extension(chan, chan->context, "o", 1,
05710          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05711          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05712          ouseexten = 1;
05713       } else if (!ast_strlen_zero(chan->macrocontext)
05714          && ast_exists_extension(chan, chan->macrocontext, "o", 1,
05715             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05716          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05717          ousemacro = 1;
05718       }
05719    }
05720 
05721    if (!ast_strlen_zero(vmu->exit)) {
05722       if (ast_exists_extension(chan, vmu->exit, "a", 1,
05723          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05724          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05725       }
05726    } else if (ast_exists_extension(chan, chan->context, "a", 1,
05727       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05728       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05729    } else if (!ast_strlen_zero(chan->macrocontext)
05730       && ast_exists_extension(chan, chan->macrocontext, "a", 1,
05731          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05732       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05733       ausemacro = 1;
05734    }
05735 
05736    if (ast_test_flag(options, OPT_DTMFEXIT)) {
05737       for (code = alldtmf; *code; code++) {
05738          char e[2] = "";
05739          e[0] = *code;
05740          if (strchr(ecodes, e[0]) == NULL
05741             && ast_canmatch_extension(chan, chan->context, e, 1,
05742                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05743             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
05744          }
05745       }
05746    }
05747 
05748    /* Play the beginning intro if desired */
05749    if (!ast_strlen_zero(prefile)) {
05750 #ifdef ODBC_STORAGE
05751       int success = 
05752 #endif
05753          RETRIEVE(prefile, -1, ext, context);
05754       if (ast_fileexists(prefile, NULL, NULL) > 0) {
05755          if (ast_streamfile(chan, prefile, chan->language) > -1) 
05756             res = ast_waitstream(chan, ecodes);
05757 #ifdef ODBC_STORAGE
05758          if (success == -1) {
05759             /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
05760             ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
05761             store_file(prefile, vmu->mailbox, vmu->context, -1);
05762          }
05763 #endif
05764       } else {
05765          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
05766          res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
05767       }
05768       DISPOSE(prefile, -1);
05769       if (res < 0) {
05770          ast_debug(1, "Hang up during prefile playback\n");
05771          free_user(vmu);
05772          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05773          ast_free(tmp);
05774          return -1;
05775       }
05776    }
05777    if (res == '#') {
05778       /* On a '#' we skip the instructions */
05779       ast_set_flag(options, OPT_SILENT);
05780       res = 0;
05781    }
05782    /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
05783    if (vmu->maxmsg == 0) {
05784       if (option_debug > 2)
05785          ast_log(LOG_DEBUG, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
05786       pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05787       goto leave_vm_out;
05788    }
05789    if (!res && !ast_test_flag(options, OPT_SILENT)) {
05790       res = ast_stream_and_wait(chan, INTRO, ecodes);
05791       if (res == '#') {
05792          ast_set_flag(options, OPT_SILENT);
05793          res = 0;
05794       }
05795    }
05796    if (res > 0)
05797       ast_stopstream(chan);
05798    /* Check for a '*' here in case the caller wants to escape from voicemail to something
05799     other than the operator -- an automated attendant or mailbox login for example */
05800    if (res == '*') {
05801       chan->exten[0] = 'a';
05802       chan->exten[1] = '\0';
05803       if (!ast_strlen_zero(vmu->exit)) {
05804          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05805       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
05806          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05807       }
05808       chan->priority = 0;
05809       free_user(vmu);
05810       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05811       ast_free(tmp);
05812       return 0;
05813    }
05814 
05815    /* Check for a '0' here */
05816    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
05817    transfer:
05818       if (ouseexten || ousemacro) {
05819          chan->exten[0] = 'o';
05820          chan->exten[1] = '\0';
05821          if (!ast_strlen_zero(vmu->exit)) {
05822             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05823          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
05824             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05825          }
05826          ast_play_and_wait(chan, "transfer");
05827          chan->priority = 0;
05828          free_user(vmu);
05829          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05830       }
05831       ast_free(tmp);
05832       return OPERATOR_EXIT;
05833    }
05834 
05835    /* Allow all other digits to exit Voicemail and return to the dialplan */
05836    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
05837       if (!ast_strlen_zero(options->exitcontext))
05838          ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
05839       free_user(vmu);
05840       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05841       ast_free(tmp);
05842       return res;
05843    }
05844 
05845    if (res < 0) {
05846       free_user(vmu);
05847       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05848       ast_free(tmp);
05849       return -1;
05850    }
05851    /* The meat of recording the message...  All the announcements and beeps have been played*/
05852    ast_copy_string(fmt, vmfmts, sizeof(fmt));
05853    if (!ast_strlen_zero(fmt)) {
05854       msgnum = 0;
05855 
05856 #ifdef IMAP_STORAGE
05857       /* Is ext a mailbox? */
05858       /* must open stream for this user to get info! */
05859       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
05860       if (res < 0) {
05861          ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
05862          ast_free(tmp);
05863          return -1;
05864       }
05865       if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
05866       /* It is possible under certain circumstances that inboxcount did not
05867        * create a vm_state when it was needed. This is a catchall which will
05868        * rarely be used.
05869        */
05870          if (!(vms = create_vm_state_from_user(vmu))) {
05871             ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
05872             ast_free(tmp);
05873             return -1;
05874          }
05875       }
05876       vms->newmessages++;
05877       
05878       /* here is a big difference! We add one to it later */
05879       msgnum = newmsgs + oldmsgs;
05880       ast_debug(3, "Messagecount set to %d\n", msgnum);
05881       snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
05882       /* set variable for compatibility */
05883       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05884 
05885       if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
05886          goto leave_vm_out;
05887       }
05888 #else
05889       if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
05890          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05891          if (!res)
05892             res = ast_waitstream(chan, "");
05893          ast_log(AST_LOG_WARNING, "No more messages possible\n");
05894          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05895          inprocess_count(vmu->mailbox, vmu->context, -1);
05896          goto leave_vm_out;
05897       }
05898 
05899 #endif
05900       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
05901       txtdes = mkstemp(tmptxtfile);
05902       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
05903       if (txtdes < 0) {
05904          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05905          if (!res)
05906             res = ast_waitstream(chan, "");
05907          ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
05908          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05909          inprocess_count(vmu->mailbox, vmu->context, -1);
05910          goto leave_vm_out;
05911       }
05912 
05913       /* Now play the beep once we have the message number for our next message. */
05914       if (res >= 0) {
05915          /* Unless we're *really* silent, try to send the beep */
05916          res = ast_stream_and_wait(chan, "beep", "");
05917       }
05918             
05919       /* Store information in real-time storage */
05920       if (ast_check_realtime("voicemail_data")) {
05921          snprintf(priority, sizeof(priority), "%d", chan->priority);
05922          snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
05923          get_date(date, sizeof(date));
05924          ast_callerid_merge(callerid, sizeof(callerid),
05925             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05926             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05927             "Unknown");
05928          ast_store_realtime("voicemail_data",
05929             "origmailbox", ext,
05930             "context", chan->context,
05931             "macrocontext", chan->macrocontext,
05932             "exten", chan->exten,
05933             "priority", priority,
05934             "callerchan", chan->name,
05935             "callerid", callerid,
05936             "origdate", date,
05937             "origtime", origtime,
05938             "category", S_OR(category, ""),
05939             "filename", tmptxtfile,
05940             SENTINEL);
05941       }
05942 
05943       /* Store information */
05944       txt = fdopen(txtdes, "w+");
05945       if (txt) {
05946          get_date(date, sizeof(date));
05947          ast_callerid_merge(callerid, sizeof(callerid),
05948             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05949             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05950             "Unknown");
05951          fprintf(txt, 
05952             ";\n"
05953             "; Message Information file\n"
05954             ";\n"
05955             "[message]\n"
05956             "origmailbox=%s\n"
05957             "context=%s\n"
05958             "macrocontext=%s\n"
05959             "exten=%s\n"
05960             "rdnis=%s\n"
05961             "priority=%d\n"
05962             "callerchan=%s\n"
05963             "callerid=%s\n"
05964             "origdate=%s\n"
05965             "origtime=%ld\n"
05966             "category=%s\n",
05967             ext,
05968             chan->context,
05969             chan->macrocontext, 
05970             chan->exten,
05971             S_COR(chan->redirecting.from.number.valid,
05972                chan->redirecting.from.number.str, "unknown"),
05973             chan->priority,
05974             chan->name,
05975             callerid,
05976             date, (long) time(NULL),
05977             category ? category : "");
05978       } else {
05979          ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
05980          inprocess_count(vmu->mailbox, vmu->context, -1);
05981          if (ast_check_realtime("voicemail_data")) {
05982             ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05983          }
05984          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05985          goto leave_vm_out;
05986       }
05987       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag);
05988 
05989       if (txt) {
05990          fprintf(txt, "flag=%s\n", flag);
05991          if (sound_duration < vmu->minsecs) {
05992             fclose(txt);
05993             ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->minsecs);
05994             ast_filedelete(tmptxtfile, NULL);
05995             unlink(tmptxtfile);
05996             if (ast_check_realtime("voicemail_data")) {
05997                ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05998             }
05999             inprocess_count(vmu->mailbox, vmu->context, -1);
06000          } else {
06001             fprintf(txt, "duration=%d\n", duration);
06002             fclose(txt);
06003             if (vm_lock_path(dir)) {
06004                ast_log(AST_LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
06005                /* Delete files */
06006                ast_filedelete(tmptxtfile, NULL);
06007                unlink(tmptxtfile);
06008                inprocess_count(vmu->mailbox, vmu->context, -1);
06009             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
06010                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
06011                unlink(tmptxtfile);
06012                ast_unlock_path(dir);
06013                inprocess_count(vmu->mailbox, vmu->context, -1);
06014                if (ast_check_realtime("voicemail_data")) {
06015                   ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
06016                }
06017             } else {
06018 #ifndef IMAP_STORAGE
06019                msgnum = last_message_index(vmu, dir) + 1;
06020 #endif
06021                make_file(fn, sizeof(fn), dir, msgnum);
06022 
06023                /* assign a variable with the name of the voicemail file */ 
06024 #ifndef IMAP_STORAGE
06025                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
06026 #else
06027                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
06028 #endif
06029 
06030                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
06031                ast_filerename(tmptxtfile, fn, NULL);
06032                rename(tmptxtfile, txtfile);
06033                inprocess_count(vmu->mailbox, vmu->context, -1);
06034 
06035                /* Properly set permissions on voicemail text descriptor file.
06036                   Unfortunately mkstemp() makes this file 0600 on most unix systems. */
06037                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
06038                   ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
06039 
06040                ast_unlock_path(dir);
06041                if (ast_check_realtime("voicemail_data")) {
06042                   snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
06043                   ast_update_realtime("voicemail_data", "filename", tmptxtfile, "filename", fn, "duration", tmpdur, SENTINEL);
06044                }
06045                /* We must store the file first, before copying the message, because
06046                 * ODBC storage does the entire copy with SQL.
06047                 */
06048                if (ast_fileexists(fn, NULL, NULL) > 0) {
06049                   STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag);
06050                }
06051 
06052                /* Are there to be more recipients of this message? */
06053                while (tmpptr) {
06054                   struct ast_vm_user recipu, *recip;
06055                   char *exten, *cntx;
06056 
06057                   exten = strsep(&tmpptr, "&");
06058                   cntx = strchr(exten, '@');
06059                   if (cntx) {
06060                      *cntx = '\0';
06061                      cntx++;
06062                   }
06063                   if ((recip = find_user(&recipu, cntx, exten))) {
06064                      copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
06065                      free_user(recip);
06066                   }
06067                }
06068 #ifndef IMAP_STORAGE
06069                if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If this is an Urgent message */
06070                   /* Move the message from INBOX to Urgent folder if this is urgent! */
06071                   char sfn[PATH_MAX];
06072                   char dfn[PATH_MAX];
06073                   int x;
06074                   /* It's easier just to try to make it than to check for its existence */
06075                   create_dirpath(urgdir, sizeof(urgdir), vmu->context, ext, "Urgent");
06076                   x = last_message_index(vmu, urgdir) + 1;
06077                   make_file(sfn, sizeof(sfn), dir, msgnum);
06078                   make_file(dfn, sizeof(dfn), urgdir, x);
06079                   ast_debug(5, "Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
06080                   RENAME(dir, msgnum, vmu->mailbox, vmu->context, urgdir, x, sfn, dfn);
06081                   /* Notification must happen for this new message in Urgent folder, not INBOX */
06082                   ast_copy_string(fn, dfn, sizeof(fn));
06083                   msgnum = x;
06084                }
06085 #endif
06086                /* Notification needs to happen after the copy, though. */
06087                if (ast_fileexists(fn, NULL, NULL)) {
06088 #ifdef IMAP_STORAGE
06089                   notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
06090                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
06091                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
06092                      flag);
06093 #else
06094                   notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
06095                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
06096                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
06097                      flag);
06098 #endif
06099                }
06100 
06101                /* Disposal needs to happen after the optional move and copy */
06102                if (ast_fileexists(fn, NULL, NULL)) {
06103                   DISPOSE(dir, msgnum);
06104                }
06105             }
06106          }
06107       } else {
06108          inprocess_count(vmu->mailbox, vmu->context, -1);
06109       }
06110       if (res == '0') {
06111          goto transfer;
06112       } else if (res > 0 && res != 't')
06113          res = 0;
06114 
06115       if (sound_duration < vmu->minsecs)
06116          /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
06117          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
06118       else
06119          pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
06120    } else
06121       ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
06122 leave_vm_out:
06123    free_user(vmu);
06124 
06125 #ifdef IMAP_STORAGE
06126    /* expunge message - use UID Expunge if supported on IMAP server*/
06127    ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
06128    if (expungeonhangup == 1) {
06129       ast_mutex_lock(&vms->lock);
06130 #ifdef HAVE_IMAP_TK2006
06131       if (LEVELUIDPLUS (vms->mailstream)) {
06132          mail_expunge_full(vms->mailstream, NIL, EX_UID);
06133       } else 
06134 #endif
06135          mail_expunge(vms->mailstream);
06136       ast_mutex_unlock(&vms->lock);
06137    }
06138 #endif
06139 
06140    ast_free(tmp);
06141    return res;
06142 }

static int load_config ( int  reload  )  [static]

Definition at line 11779 of file app_voicemail_imapstorage.c.

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

11780 {
11781    struct ast_config *cfg, *ucfg;
11782    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11783    int res;
11784 
11785    ast_unload_realtime("voicemail");
11786    ast_unload_realtime("voicemail_data");
11787 
11788    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11789       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11790          return 0;
11791       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11792          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11793          ucfg = NULL;
11794       }
11795       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11796       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11797          ast_config_destroy(ucfg);
11798          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11799          return 0;
11800       }
11801    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11802       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11803       return 0;
11804    } else {
11805       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11806       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11807          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11808          ucfg = NULL;
11809       }
11810    }
11811 
11812    res = actual_load_config(reload, cfg, ucfg);
11813 
11814    ast_config_destroy(cfg);
11815    ast_config_destroy(ucfg);
11816 
11817    return res;
11818 }

static int load_module ( void   )  [static]

Definition at line 13070 of file app_voicemail_imapstorage.c.

References ao2_container_alloc, app, app2, app3, app4, ARRAY_LEN, ast_cli_register_multiple(), ast_config_AST_SPOOL_DIR, ast_custom_function_register, ast_data_register_multiple, ast_install_vm_functions(), ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_realtime_require_field(), ast_register_application_xml, ast_taskprocessor_get(), AST_TEST_REGISTER, cli_voicemail, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, has_voicemail(), inboxcount(), inboxcount2(), inprocess_cmp_fn(), inprocess_container, inprocess_hash_fn(), load_config(), mailbox_exists_acf, manager_list_voicemail_users(), messagecount(), mwi_subscription_tps, my_umask, RQ_CHAR, RQ_UINTEGER3, sayname(), sayname_app, SENTINEL, vm_box_exists(), vm_data_providers, vm_exec(), vm_execmain(), VM_SPOOL_DIR, vmauthenticate(), and vmsayname_exec().

13071 {
13072    int res;
13073    my_umask = umask(0);
13074    umask(my_umask);
13075 
13076    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
13077       return AST_MODULE_LOAD_DECLINE;
13078    }
13079 
13080    /* compute the location of the voicemail spool directory */
13081    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13082    
13083    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13084       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
13085    }
13086 
13087    if ((res = load_config(0)))
13088       return res;
13089 
13090    res = ast_register_application_xml(app, vm_exec);
13091    res |= ast_register_application_xml(app2, vm_execmain);
13092    res |= ast_register_application_xml(app3, vm_box_exists);
13093    res |= ast_register_application_xml(app4, vmauthenticate);
13094    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
13095    res |= ast_custom_function_register(&mailbox_exists_acf);
13096    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
13097 #ifdef TEST_FRAMEWORK
13098    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13099    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13100    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13101    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13102    res |= AST_TEST_REGISTER(test_voicemail_load_config);
13103 #endif
13104 
13105    if (res)
13106       return res;
13107 
13108    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13109    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
13110 
13111    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
13112    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13113    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13114 
13115    return res;
13116 }

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:
dest The variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
len The 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 1643 of file app_voicemail_imapstorage.c.

References VM_SPOOL_DIR.

01644 {
01645    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01646 }

static void make_email_file ( FILE *  p,
char *  srcemail,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  attach,
char *  attach2,
char *  format,
int  duration,
int  attach_user_voicemail,
struct ast_channel chan,
const char *  category,
int  imap,
const char *  flag 
) [static]

Creates the email file to be sent to indicate a new voicemail exists for a user.

Parameters:
p The output file to generate the email contents into.
srcemail The email address to send the email to, presumably the email address for the owner of the mailbox.
vmu The voicemail user who is sending the voicemail.
msgnum The message index in the mailbox folder.
context 
mailbox The voicemail box to read the voicemail to be notified in this email.
fromfolder 
cidnum The caller ID number.
cidname The caller ID name.
attach the name of the sound file to be attached to the email, if attach_user_voicemail == 1.
attach2 
format The message sound file format. i.e. .wav
duration The time of the message content, in seconds.
attach_user_voicemail if 1, the sound file is attached to the email.
chan 
category 
imap if == 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 The email body, and base 64 encoded attachement (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.

Definition at line 4525 of file app_voicemail_imapstorage.c.

References add_email_attachment(), ast_channel_unref, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_localtime(), ast_log(), ast_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_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, emailbody, emaildateformat, ast_vm_user::emailsubject, emailsubject, ENDL, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, ast_channel::name, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

04526 {
04527    char date[256];
04528    char host[MAXHOSTNAMELEN] = "";
04529    char who[256];
04530    char bound[256];
04531    char dur[256];
04532    struct ast_tm tm;
04533    char enc_cidnum[256] = "", enc_cidname[256] = "";
04534    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04535    char *greeting_attachment; 
04536    char filename[256];
04537 
04538    if (!str1 || !str2) {
04539       ast_free(str1);
04540       ast_free(str2);
04541       return;
04542    }
04543 
04544    if (cidnum) {
04545       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04546    }
04547    if (cidname) {
04548       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04549    }
04550    gethostname(host, sizeof(host) - 1);
04551 
04552    if (strchr(srcemail, '@')) {
04553       ast_copy_string(who, srcemail, sizeof(who));
04554    } else {
04555       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04556    }
04557 
04558    greeting_attachment = strrchr(ast_strdupa(attach), '/');
04559    if (greeting_attachment) {
04560       *greeting_attachment++ = '\0';
04561    }
04562 
04563    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04564    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04565    fprintf(p, "Date: %s" ENDL, date);
04566 
04567    /* Set date format for voicemail mail */
04568    ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04569 
04570    if (!ast_strlen_zero(fromstring)) {
04571       struct ast_channel *ast;
04572       if ((ast = ast_dummy_channel_alloc())) {
04573          char *ptr;
04574          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04575          ast_str_substitute_variables(&str1, 0, ast, fromstring);
04576 
04577          if (check_mime(ast_str_buffer(str1))) {
04578             int first_line = 1;
04579             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04580             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04581                *ptr = '\0';
04582                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04583                first_line = 0;
04584                /* Substring is smaller, so this will never grow */
04585                ast_str_set(&str2, 0, "%s", ptr + 1);
04586             }
04587             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04588          } else {
04589             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04590          }
04591          ast = ast_channel_unref(ast);
04592       } else {
04593          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04594       }
04595    } else {
04596       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04597    }
04598 
04599    if (check_mime(vmu->fullname)) {
04600       int first_line = 1;
04601       char *ptr;
04602       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(vmu->email) + 3);
04603       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04604          *ptr = '\0';
04605          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04606          first_line = 0;
04607          /* Substring is smaller, so this will never grow */
04608          ast_str_set(&str2, 0, "%s", ptr + 1);
04609       }
04610       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), vmu->email);
04611    } else {
04612       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), vmu->email);
04613    }
04614 
04615    if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
04616       char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
04617       struct ast_channel *ast;
04618       if ((ast = ast_dummy_channel_alloc())) {
04619          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04620          ast_str_substitute_variables(&str1, 0, ast, e_subj);
04621          if (check_mime(ast_str_buffer(str1))) {
04622             int first_line = 1;
04623             char *ptr;
04624             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04625             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04626                *ptr = '\0';
04627                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04628                first_line = 0;
04629                /* Substring is smaller, so this will never grow */
04630                ast_str_set(&str2, 0, "%s", ptr + 1);
04631             }
04632             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04633          } else {
04634             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04635          }
04636          ast = ast_channel_unref(ast);
04637       } else {
04638          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04639       }
04640    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
04641       if (ast_strlen_zero(flag)) {
04642          fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04643       } else {
04644          fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04645       }
04646    } else {
04647       if (ast_strlen_zero(flag)) {
04648          fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04649       } else {
04650          fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04651       }
04652    }
04653 
04654    fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1,
04655       (unsigned int) ast_random(), mailbox, (int) getpid(), host);
04656    if (imap) {
04657       /* additional information needed for IMAP searching */
04658       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
04659       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
04660       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
04661       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
04662 #ifdef IMAP_STORAGE
04663       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
04664 #else
04665       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
04666 #endif
04667       /* flag added for Urgent */
04668       fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
04669       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
04670       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
04671       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
04672       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
04673       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
04674       if (!ast_strlen_zero(category)) {
04675          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
04676       } else {
04677          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
04678       }
04679       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
04680       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
04681       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long) time(NULL));
04682    }
04683    if (!ast_strlen_zero(cidnum)) {
04684       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
04685    }
04686    if (!ast_strlen_zero(cidname)) {
04687       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
04688    }
04689    fprintf(p, "MIME-Version: 1.0" ENDL);
04690    if (attach_user_voicemail) {
04691       /* Something unique. */
04692       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox,
04693          (int) getpid(), (unsigned int) ast_random());
04694 
04695       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
04696       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
04697       fprintf(p, "--%s" ENDL, bound);
04698    }
04699    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
04700    if (emailbody || vmu->emailbody) {
04701       char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
04702       struct ast_channel *ast;
04703       if ((ast = ast_dummy_channel_alloc())) {
04704          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04705          ast_str_substitute_variables(&str1, 0, ast, e_body);
04706 #ifdef IMAP_STORAGE
04707             {
04708                /* Convert body to native line terminators for IMAP backend */
04709                char *line = ast_str_buffer(str1), *next;
04710                do {
04711                   /* Terminate line before outputting it to the file */
04712                   if ((next = strchr(line, '\n'))) {
04713                      *next++ = '\0';
04714                   }
04715                   fprintf(p, "%s" ENDL, line);
04716                   line = next;
04717                } while (!ast_strlen_zero(line));
04718             }
04719 #else
04720          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
04721 #endif
04722          ast = ast_channel_unref(ast);
04723       } else {
04724          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04725       }
04726    } else if (msgnum > -1) {
04727       if (strcmp(vmu->mailbox, mailbox)) {
04728          /* Forwarded type */
04729          struct ast_config *msg_cfg;
04730          const char *v;
04731          int inttime;
04732          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
04733          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04734          /* Retrieve info from VM attribute file */
04735          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04736          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
04737          if (strlen(fromfile) < sizeof(fromfile) - 5) {
04738             strcat(fromfile, ".txt");
04739          }
04740          if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
04741             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04742                ast_copy_string(origcallerid, v, sizeof(origcallerid));
04743             }
04744 
04745             /* You might be tempted to do origdate, except that a) it's in the wrong
04746              * format, and b) it's missing for IMAP recordings. */
04747             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
04748                struct timeval tv = { inttime, };
04749                struct ast_tm tm;
04750                ast_localtime(&tv, &tm, NULL);
04751                ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04752             }
04753             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
04754                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
04755                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
04756                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
04757                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
04758                date, origcallerid, origdate);
04759             ast_config_destroy(msg_cfg);
04760          } else {
04761             goto plain_message;
04762          }
04763       } else {
04764 plain_message:
04765          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
04766             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
04767             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
04768             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
04769             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
04770       }
04771    } else {
04772       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
04773             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
04774    }
04775 
04776    if (imap || attach_user_voicemail) {
04777       if (!ast_strlen_zero(attach2)) {
04778          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04779          ast_debug(5, "creating second attachment filename %s\n", filename);
04780          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
04781          snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
04782          ast_debug(5, "creating attachment filename %s\n", filename);
04783          add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04784       } else {
04785          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04786          ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
04787          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04788       }
04789    }
04790    ast_free(str1);
04791    ast_free(str2);
04792 }

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:
dest The variable to hold the output generated path expression. This buffer should be of size PATH_MAX.
len The 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 1660 of file app_voicemail_imapstorage.c.

01661 {
01662    return snprintf(dest, len, "%s/msg%04d", dir, num);
01663 }

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

Manager list voicemail users command.

Definition at line 11610 of file app_voicemail_imapstorage.c.

References AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), astman_send_ack(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::context, count_messages(), ast_vm_user::dialout, ast_vm_user::email, ast_vm_user::exit, ast_vm_user::fullname, inboxcount(), ast_vm_user::language, ast_vm_user::list, ast_vm_user::mailbox, ast_vm_user::mailcmd, make_dir(), ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::pager, RESULT_SUCCESS, ast_vm_user::saydurationm, ast_vm_user::serveremail, ast_vm_user::uniqueid, VM_ATTACH, VM_DELETE, VM_ENVELOPE, VM_OPERATOR, VM_REVIEW, VM_SAYCID, ast_vm_user::volgain, and ast_vm_user::zonetag.

11611 {
11612    struct ast_vm_user *vmu = NULL;
11613    const char *id = astman_get_header(m, "ActionID");
11614    char actionid[128] = "";
11615 
11616    if (!ast_strlen_zero(id))
11617       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11618 
11619    AST_LIST_LOCK(&users);
11620 
11621    if (AST_LIST_EMPTY(&users)) {
11622       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11623       AST_LIST_UNLOCK(&users);
11624       return RESULT_SUCCESS;
11625    }
11626    
11627    astman_send_ack(s, m, "Voicemail user list will follow");
11628    
11629    AST_LIST_TRAVERSE(&users, vmu, list) {
11630       char dirname[256];
11631 
11632 #ifdef IMAP_STORAGE
11633       int new, old;
11634       inboxcount(vmu->mailbox, &new, &old);
11635 #endif
11636       
11637       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11638       astman_append(s,
11639          "%s"
11640          "Event: VoicemailUserEntry\r\n"
11641          "VMContext: %s\r\n"
11642          "VoiceMailbox: %s\r\n"
11643          "Fullname: %s\r\n"
11644          "Email: %s\r\n"
11645          "Pager: %s\r\n"
11646          "ServerEmail: %s\r\n"
11647          "MailCommand: %s\r\n"
11648          "Language: %s\r\n"
11649          "TimeZone: %s\r\n"
11650          "Callback: %s\r\n"
11651          "Dialout: %s\r\n"
11652          "UniqueID: %s\r\n"
11653          "ExitContext: %s\r\n"
11654          "SayDurationMinimum: %d\r\n"
11655          "SayEnvelope: %s\r\n"
11656          "SayCID: %s\r\n"
11657          "AttachMessage: %s\r\n"
11658          "AttachmentFormat: %s\r\n"
11659          "DeleteMessage: %s\r\n"
11660          "VolumeGain: %.2f\r\n"
11661          "CanReview: %s\r\n"
11662          "CallOperator: %s\r\n"
11663          "MaxMessageCount: %d\r\n"
11664          "MaxMessageLength: %d\r\n"
11665          "NewMessageCount: %d\r\n"
11666 #ifdef IMAP_STORAGE
11667          "OldMessageCount: %d\r\n"
11668          "IMAPUser: %s\r\n"
11669 #endif
11670          "\r\n",
11671          actionid,
11672          vmu->context,
11673          vmu->mailbox,
11674          vmu->fullname,
11675          vmu->email,
11676          vmu->pager,
11677          vmu->serveremail,
11678          vmu->mailcmd,
11679          vmu->language,
11680          vmu->zonetag,
11681          vmu->callback,
11682          vmu->dialout,
11683          vmu->uniqueid,
11684          vmu->exit,
11685          vmu->saydurationm,
11686          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11687          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11688          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11689          vmu->attachfmt,
11690          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11691          vmu->volgain,
11692          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11693          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11694          vmu->maxmsg,
11695          vmu->maxsecs,
11696 #ifdef IMAP_STORAGE
11697          new, old, vmu->imapuser
11698 #else
11699          count_messages(vmu, dirname)
11700 #endif
11701          );
11702    }     
11703    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11704 
11705    AST_LIST_UNLOCK(&users);
11706 
11707    return RESULT_SUCCESS;
11708 }

static void* mb_poll_thread ( void *  data  )  [static]

Definition at line 11444 of file app_voicemail_imapstorage.c.

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

11445 {
11446    while (poll_thread_run) {
11447       struct timespec ts = { 0, };
11448       struct timeval wait;
11449 
11450       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11451       ts.tv_sec = wait.tv_sec;
11452       ts.tv_nsec = wait.tv_usec * 1000;
11453 
11454       ast_mutex_lock(&poll_lock);
11455       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11456       ast_mutex_unlock(&poll_lock);
11457 
11458       if (!poll_thread_run)
11459          break;
11460 
11461       poll_subscribed_mailboxes();
11462    }
11463 
11464    return NULL;
11465 }

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

Definition at line 1721 of file app_voicemail_imapstorage.c.

References ARRAY_LEN.

01722 {
01723 #ifdef IMAP_STORAGE
01724    if (vmu && id == 0) {
01725       return vmu->imapfolder;
01726    }
01727 #endif
01728    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01729 }

static int messagecount ( const char *  context,
const char *  mailbox,
const char *  folder 
) [static]

Definition at line 5375 of file app_voicemail_imapstorage.c.

References __has_voicemail().

05376 {
05377    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05378 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11467 of file app_voicemail_imapstorage.c.

References ast_free, and mwi_sub.

11468 {
11469    ast_free(mwi_sub);
11470 }

static void mwi_sub_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 11545 of file app_voicemail_imapstorage.c.

References ast_calloc, ast_event_get_ie_str(), ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_SUB, ast_free, ast_log(), ast_strdup, ast_taskprocessor_push(), handle_subscribe(), LOG_ERROR, and mwi_subscription_tps.

11546 {
11547    struct mwi_sub_task *mwist;
11548    
11549    if (ast_event_get_type(event) != AST_EVENT_SUB)
11550       return;
11551 
11552    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11553       return;
11554 
11555    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11556       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11557       return;
11558    }
11559    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11560    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11561    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11562    
11563    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11564       ast_free(mwist);
11565    }
11566 }

static void mwi_unsub_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 11529 of file app_voicemail_imapstorage.c.

References ast_calloc, ast_event_get_ie_uint(), ast_event_get_type(), AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_UNIQUEID, AST_EVENT_MWI, AST_EVENT_UNSUB, ast_free, ast_taskprocessor_push(), handle_unsubscribe(), mwi_subscription_tps, and mwi_sub_task::uniqueid.

11530 {
11531    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11532    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
11533       return;
11534 
11535    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11536       return;
11537 
11538    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11539    *uniqueid = u;
11540    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11541       ast_free(uniqueid);
11542    }
11543 }

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 
cidnum The Caller ID phone number value.
cidname The Caller ID name value.
flag 
Returns:
zero on success, -1 on error.

Definition at line 7040 of file app_voicemail_imapstorage.c.

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

07041 {
07042    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07043    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07044    const char *category;
07045    char *myserveremail = serveremail;
07046 
07047    ast_channel_lock(chan);
07048    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07049       category = ast_strdupa(category);
07050    }
07051    ast_channel_unlock(chan);
07052 
07053 #ifndef IMAP_STORAGE
07054    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07055 #else
07056    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07057 #endif
07058    make_file(fn, sizeof(fn), todir, msgnum);
07059    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07060 
07061    if (!ast_strlen_zero(vmu->attachfmt)) {
07062       if (strstr(fmt, vmu->attachfmt))
07063          fmt = vmu->attachfmt;
07064       else
07065          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);
07066    }
07067 
07068    /* Attach only the first format */
07069    fmt = ast_strdupa(fmt);
07070    stringp = fmt;
07071    strsep(&stringp, "|");
07072 
07073    if (!ast_strlen_zero(vmu->serveremail))
07074       myserveremail = vmu->serveremail;
07075 
07076    if (!ast_strlen_zero(vmu->email)) {
07077       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07078 
07079       if (attach_user_voicemail)
07080          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07081 
07082       /* XXX possible imap issue, should category be NULL XXX */
07083       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07084 
07085       if (attach_user_voicemail)
07086          DISPOSE(todir, msgnum);
07087    }
07088 
07089    if (!ast_strlen_zero(vmu->pager)) {
07090       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07091    }
07092 
07093    if (ast_test_flag(vmu, VM_DELETE))
07094       DELETE(todir, msgnum, fn, vmu);
07095 
07096    /* Leave voicemail for someone */
07097    if (ast_app_has_voicemail(ext_context, NULL)) 
07098       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07099 
07100    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07101 
07102    ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
07103    run_externnotify(vmu->context, vmu->mailbox, flag);
07104 
07105 #ifdef IMAP_STORAGE
07106    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07107    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07108       vm_imap_delete(NULL, vms->curmsg, vmu);
07109       vms->newmessages--;  /* Fix new message count */
07110    }
07111 #endif
07112 
07113    return 0;
07114 }

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

utility used by base_encode()

Definition at line 4245 of file app_voicemail_imapstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

04246 {
04247    if (bio->linelength >= BASELINELEN) {
04248       if (fputs(ENDL, so) == EOF) {
04249          return -1;
04250       }
04251 
04252       bio->linelength = 0;
04253    }
04254 
04255    if (putc(((unsigned char) c), so) == EOF) {
04256       return -1;
04257    }
04258 
04259    bio->linelength++;
04260 
04261    return 1;
04262 }

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

Definition at line 7885 of file app_voicemail_imapstorage.c.

References ast_copy_string(), ast_log(), AST_LOG_ERROR, ast_unlock_path(), ast_vm_user::context, count_messages(), create_dirpath(), vm_state::curbox, vm_state::curdir, ERROR_LOCK_PATH, last_message_index(), vm_state::lastmsg, LOG_NOTICE, ast_vm_user::maxmsg, mbox(), resequence_mailbox(), vm_state::username, vm_allocate_dh(), vm_lock_path(), and vm_state::vmbox.

07886 {
07887    int count_msg, last_msg;
07888 
07889    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07890 
07891    /* Rename the member vmbox HERE so that we don't try to return before
07892     * we know what's going on.
07893     */
07894    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07895 
07896    /* Faster to make the directory than to check if it exists. */
07897    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07898 
07899    /* traverses directory using readdir (or select query for ODBC) */
07900    count_msg = count_messages(vmu, vms->curdir);
07901    if (count_msg < 0) {
07902       return count_msg;
07903    } else {
07904       vms->lastmsg = count_msg - 1;
07905    }
07906 
07907    if (vm_allocate_dh(vms, vmu, count_msg)) {
07908       return -1;
07909    }
07910 
07911    /*
07912    The following test is needed in case sequencing gets messed up.
07913    There appears to be more than one way to mess up sequence, so
07914    we will not try to find all of the root causes--just fix it when
07915    detected.
07916    */
07917 
07918    if (vm_lock_path(vms->curdir)) {
07919       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07920       return ERROR_LOCK_PATH;
07921    }
07922 
07923    /* for local storage, checks directory for messages up to maxmsg limit */
07924    last_msg = last_message_index(vmu, vms->curdir);
07925    ast_unlock_path(vms->curdir);
07926 
07927    if (last_msg < -1) {
07928       return last_msg;
07929    } else if (vms->lastmsg != last_msg) {
07930       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);
07931       resequence_mailbox(vmu, vms->curdir, count_msg);
07932    }
07933 
07934    return 0;
07935 }

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

Definition at line 7663 of file app_voicemail_imapstorage.c.

References adsi_message(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log(), ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, config_flags, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, DISPOSE, vm_state::fn, vm_state::heard, ast_channel::language, vm_state::lastmsg, LOG_WARNING, ast_vm_user::mailbox, make_file(), play_message_callerid(), play_message_category(), play_message_datetime(), play_message_duration(), RETRIEVE, ast_vm_user::saydurationm, vm_state::starting, VM_ENVELOPE, VM_SAYCID, VM_SAYDURATION, wait_file(), and wait_file2().

07664 {
07665    int res = 0;
07666    char filename[256], *cid;
07667    const char *origtime, *context, *category, *duration, *flag;
07668    struct ast_config *msg_cfg;
07669    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
07670 
07671    vms->starting = 0;
07672    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07673    adsi_message(chan, vms);
07674    if (!vms->curmsg) {
07675       res = wait_file2(chan, vms, "vm-first");  /* "First" */
07676    } else if (vms->curmsg == vms->lastmsg) {
07677       res = wait_file2(chan, vms, "vm-last");      /* "last" */
07678    }
07679 
07680    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
07681    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
07682    msg_cfg = ast_config_load(filename, config_flags);
07683    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
07684       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07685       return 0;
07686    }
07687    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
07688 
07689    /* Play the word urgent if we are listening to urgent messages */
07690    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07691       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07692    }
07693 
07694    if (!res) {
07695       /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
07696       /* POLISH syntax */
07697       if (!strncasecmp(chan->language, "pl", 2)) {
07698          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07699             int ten, one;
07700             char nextmsg[256];
07701             ten = (vms->curmsg + 1) / 10;
07702             one = (vms->curmsg + 1) % 10;
07703 
07704             if (vms->curmsg < 20) {
07705                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07706                res = wait_file2(chan, vms, nextmsg);
07707             } else {
07708                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07709                res = wait_file2(chan, vms, nextmsg);
07710                if (one > 0) {
07711                   if (!res) {
07712                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07713                      res = wait_file2(chan, vms, nextmsg);
07714                   }
07715                }
07716             }
07717          }
07718          if (!res)
07719             res = wait_file2(chan, vms, "vm-message");
07720       /* HEBREW syntax */
07721       } else if (!strncasecmp(chan->language, "he", 2)) {
07722          if (!vms->curmsg) {
07723             res = wait_file2(chan, vms, "vm-message");
07724             res = wait_file2(chan, vms, "vm-first");
07725          } else if (vms->curmsg == vms->lastmsg) {
07726             res = wait_file2(chan, vms, "vm-message");
07727             res = wait_file2(chan, vms, "vm-last");
07728          } else {
07729             res = wait_file2(chan, vms, "vm-message");
07730             res = wait_file2(chan, vms, "vm-number");
07731             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07732          }
07733       /* VIETNAMESE syntax */
07734       } else if (!strncasecmp(chan->language, "vi", 2)) {
07735          if (!vms->curmsg) {
07736             res = wait_file2(chan, vms, "vm-message");
07737             res = wait_file2(chan, vms, "vm-first");
07738          } else if (vms->curmsg == vms->lastmsg) {
07739             res = wait_file2(chan, vms, "vm-message");
07740             res = wait_file2(chan, vms, "vm-last");
07741          } else {
07742             res = wait_file2(chan, vms, "vm-message");
07743             res = wait_file2(chan, vms, "vm-number");
07744             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07745          }
07746       } else {
07747          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07748             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07749          } else { /* DEFAULT syntax */
07750             res = wait_file2(chan, vms, "vm-message");
07751          }
07752          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07753             if (!res) {
07754                ast_test_suite_event_notify("PLAYBACK", "Message: message number");
07755                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07756             }
07757          }
07758       }
07759    }
07760 
07761    if (!msg_cfg) {
07762       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07763       return 0;
07764    }
07765 
07766    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07767       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07768       DISPOSE(vms->curdir, vms->curmsg);
07769       ast_config_destroy(msg_cfg);
07770       return 0;
07771    }
07772 
07773    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07774    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07775    category = ast_variable_retrieve(msg_cfg, "message", "category");
07776 
07777    context = ast_variable_retrieve(msg_cfg, "message", "context");
07778    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
07779       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
07780    if (!res) {
07781       res = play_message_category(chan, category);
07782    }
07783    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE))) {
07784       res = play_message_datetime(chan, vmu, origtime, filename);
07785    }
07786    if ((!res) && (ast_test_flag(vmu, VM_SAYCID))) {
07787       res = play_message_callerid(chan, vms, cid, context, 0);
07788    }
07789    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION))) {
07790       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07791    }
07792    /* Allow pressing '1' to skip envelope / callerid */
07793    if (res == '1') {
07794       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
07795       res = 0;
07796    }
07797    ast_config_destroy(msg_cfg);
07798 
07799    if (!res) {
07800       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07801       vms->heard[vms->curmsg] = 1;
07802 #ifdef IMAP_STORAGE
07803       /*IMAP storage stores any prepended message from a forward
07804        * as a separate file from the rest of the message
07805        */
07806       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07807          wait_file(chan, vms, vms->introfn);
07808       }
07809 #endif
07810       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07811          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07812          res = 0;
07813       }
07814       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
07815    }
07816    DISPOSE(vms->curdir, vms->curmsg);
07817    return res;
07818 }

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

Definition at line 7549 of file app_voicemail_imapstorage.c.

References ast_callerid_parse(), ast_debug, AST_DIGIT_ANY, ast_fileexists(), ast_say_digit_str(), ast_stream_and_wait(), ast_strlen_zero(), ast_verb, cidinternalcontexts, ast_channel::language, MAX_NUM_CID_CONTEXTS, name, VM_SPOOL_DIR, and wait_file2().

07550 {
07551    int res = 0;
07552    int i;
07553    char *callerid, *name;
07554    char prefile[PATH_MAX] = "";
07555    
07556 
07557    /* If voicemail cid is not enabled, or we didn't get cid or context from
07558     * the attribute file, leave now.
07559     *
07560     * TODO Still need to change this so that if this function is called by the
07561     * message envelope (and someone is explicitly requesting to hear the CID),
07562     * it does not check to see if CID is enabled in the config file.
07563     */
07564    if ((cid == NULL)||(context == NULL))
07565       return res;
07566 
07567    /* Strip off caller ID number from name */
07568    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07569    ast_callerid_parse(cid, &name, &callerid);
07570    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07571       /* Check for internal contexts and only */
07572       /* say extension when the call didn't come from an internal context in the list */
07573       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07574          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07575          if ((strcmp(cidinternalcontexts[i], context) == 0))
07576             break;
07577       }
07578       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07579          if (!res) {
07580             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07581             if (!ast_strlen_zero(prefile)) {
07582             /* See if we can find a recorded name for this person instead of their extension number */
07583                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07584                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07585                   if (!callback)
07586                      res = wait_file2(chan, vms, "vm-from");
07587                   res = ast_stream_and_wait(chan, prefile, "");
07588                } else {
07589                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07590                   /* Say "from extension" as one saying to sound smoother */
07591                   if (!callback)
07592                      res = wait_file2(chan, vms, "vm-from-extension");
07593                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07594                }
07595             }
07596          }
07597       } else if (!res) {
07598          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07599          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07600          if (!callback)
07601             res = wait_file2(chan, vms, "vm-from-phonenumber");
07602          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07603       }
07604    } else {
07605       /* Number unknown */
07606       ast_debug(1, "VM-CID: From an unknown number\n");
07607       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07608       res = wait_file2(chan, vms, "vm-unknown-caller");
07609    }
07610    return res;
07611 }

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

Definition at line 7460 of file app_voicemail_imapstorage.c.

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

07461 {
07462    int res = 0;
07463 
07464    if (!ast_strlen_zero(category))
07465       res = ast_play_and_wait(chan, category);
07466 
07467    if (res) {
07468       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07469       res = 0;
07470    }
07471 
07472    return res;
07473 }

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

Definition at line 7475 of file app_voicemail_imapstorage.c.

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

07476 {
07477    int res = 0;
07478    struct vm_zone *the_zone = NULL;
07479    time_t t;
07480 
07481    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07482       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07483       return 0;
07484    }
07485 
07486    /* Does this user have a timezone specified? */
07487    if (!ast_strlen_zero(vmu->zonetag)) {
07488       /* Find the zone in the list */
07489       struct vm_zone *z;
07490       AST_LIST_LOCK(&zones);
07491       AST_LIST_TRAVERSE(&zones, z, list) {
07492          if (!strcmp(z->name, vmu->zonetag)) {
07493             the_zone = z;
07494             break;
07495          }
07496       }
07497       AST_LIST_UNLOCK(&zones);
07498    }
07499 
07500 /* No internal variable parsing for now, so we'll comment it out for the time being */
07501 #if 0
07502    /* Set the DIFF_* variables */
07503    ast_localtime(&t, &time_now, NULL);
07504    tv_now = ast_tvnow();
07505    ast_localtime(&tv_now, &time_then, NULL);
07506 
07507    /* Day difference */
07508    if (time_now.tm_year == time_then.tm_year)
07509       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07510    else
07511       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07512    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07513 
07514    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07515 #endif
07516    if (the_zone) {
07517       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07518    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07519       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07520    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07521       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07522    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07523       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
07524    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07525       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07526    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07527       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07528    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07529       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07530    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07531       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
07532    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07533       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07534    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07535       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07536    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07537       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' A 'digits/day' dB 'digits/year' Y 'digits/at' k 'hours' M 'minutes'", NULL);
07538    } else {
07539       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07540    }
07541 #if 0
07542    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07543 #endif
07544    return res;
07545 }

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

Definition at line 7613 of file app_voicemail_imapstorage.c.

References ast_debug, AST_DIGIT_ANY, ast_play_and_wait(), ast_say_number(), ast_channel::language, say_and_wait(), and wait_file2().

07614 {
07615    int res = 0;
07616    int durationm;
07617    int durations;
07618    /* Verify that we have a duration for the message */
07619    if (duration == NULL)
07620       return res;
07621 
07622    /* Convert from seconds to minutes */
07623    durations = atoi(duration);
07624    durationm = (durations / 60);
07625 
07626    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07627 
07628    if ((!res) && (durationm >= minduration)) {
07629       res = wait_file2(chan, vms, "vm-duration");
07630 
07631       /* POLISH syntax */
07632       if (!strncasecmp(chan->language, "pl", 2)) {
07633          div_t num = div(durationm, 10);
07634 
07635          if (durationm == 1) {
07636             res = ast_play_and_wait(chan, "digits/1z");
07637             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07638          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07639             if (num.rem == 2) {
07640                if (!num.quot) {
07641                   res = ast_play_and_wait(chan, "digits/2-ie");
07642                } else {
07643                   res = say_and_wait(chan, durationm - 2 , chan->language);
07644                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07645                }
07646             } else {
07647                res = say_and_wait(chan, durationm, chan->language);
07648             }
07649             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07650          } else {
07651             res = say_and_wait(chan, durationm, chan->language);
07652             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07653          }
07654       /* DEFAULT syntax */
07655       } else {
07656          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07657          res = wait_file2(chan, vms, "vm-minutes");
07658       }
07659    }
07660    return res;
07661 }

static int play_record_review ( struct ast_channel chan,
char *  playfile,
char *  recordfile,
int  maxtime,
char *  fmt,
int  outsidecaller,
struct ast_vm_user vmu,
int *  duration,
int *  sound_duration,
const char *  unlockdir,
signed char  record_gain,
struct vm_state vms,
char *  flag 
) [static]

Definition at line 13383 of file app_voicemail_imapstorage.c.

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

13386 {
13387    /* Record message & let caller review or re-record it, or set options if applicable */
13388    int res = 0;
13389    int cmd = 0;
13390    int max_attempts = 3;
13391    int attempts = 0;
13392    int recorded = 0;
13393    int msg_exists = 0;
13394    signed char zero_gain = 0;
13395    char tempfile[PATH_MAX];
13396    char *acceptdtmf = "#";
13397    char *canceldtmf = "";
13398    int canceleddtmf = 0;
13399 
13400    /* Note that urgent and private are for flagging messages as such in the future */
13401 
13402    /* barf if no pointer passed to store duration in */
13403    if (duration == NULL) {
13404       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
13405       return -1;
13406    }
13407 
13408    if (!outsidecaller)
13409       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
13410    else
13411       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
13412 
13413    cmd = '3';  /* Want to start by recording */
13414 
13415    while ((cmd >= 0) && (cmd != 't')) {
13416       switch (cmd) {
13417       case '1':
13418          if (!msg_exists) {
13419             /* In this case, 1 is to record a message */
13420             cmd = '3';
13421             break;
13422          } else {
13423             /* Otherwise 1 is to save the existing message */
13424             ast_verb(3, "Saving message as is\n");
13425             if (!outsidecaller) 
13426                ast_filerename(tempfile, recordfile, NULL);
13427             ast_stream_and_wait(chan, "vm-msgsaved", "");
13428             if (!outsidecaller) {
13429                /* Saves to IMAP server only if imapgreeting=yes */
13430                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
13431                DISPOSE(recordfile, -1);
13432             }
13433             cmd = 't';
13434             return res;
13435          }
13436       case '2':
13437          /* Review */
13438          ast_verb(3, "Reviewing the message\n");
13439          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13440          break;
13441       case '3':
13442          msg_exists = 0;
13443          /* Record */
13444          if (recorded == 1) 
13445             ast_verb(3, "Re-recording the message\n");
13446          else  
13447             ast_verb(3, "Recording the message\n");
13448          
13449          if (recorded && outsidecaller) {
13450             cmd = ast_play_and_wait(chan, INTRO);
13451             cmd = ast_play_and_wait(chan, "beep");
13452          }
13453          recorded = 1;
13454          /* 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 */
13455          if (record_gain)
13456             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13457          if (ast_test_flag(vmu, VM_OPERATOR))
13458             canceldtmf = "0";
13459          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13460          if (strchr(canceldtmf, cmd)) {
13461          /* need this flag here to distinguish between pressing '0' during message recording or after */
13462             canceleddtmf = 1;
13463          }
13464          if (record_gain)
13465             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13466          if (cmd == -1) {
13467             /* User has hung up, no options to give */
13468             if (!outsidecaller) {
13469                /* user was recording a greeting and they hung up, so let's delete the recording. */
13470                ast_filedelete(tempfile, NULL);
13471             }     
13472             return cmd;
13473          }
13474          if (cmd == '0') {
13475             break;
13476          } else if (cmd == '*') {
13477             break;
13478 #if 0
13479          } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
13480             /* Message is too short */
13481             ast_verb(3, "Message too short\n");
13482             cmd = ast_play_and_wait(chan, "vm-tooshort");
13483             cmd = ast_filedelete(tempfile, NULL);
13484             break;
13485          } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
13486             /* Message is all silence */
13487             ast_verb(3, "Nothing recorded\n");
13488             cmd = ast_filedelete(tempfile, NULL);
13489             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13490             if (!cmd)
13491                cmd = ast_play_and_wait(chan, "vm-speakup");
13492             break;
13493 #endif
13494          } else {
13495             /* If all is well, a message exists */
13496             msg_exists = 1;
13497             cmd = 0;
13498          }
13499          break;
13500       case '4':
13501          if (outsidecaller) {  /* only mark vm messages */
13502             /* Mark Urgent */
13503             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13504                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
13505                res = ast_play_and_wait(chan, "vm-marked-urgent");
13506                strcpy(flag, "Urgent");
13507             } else if (flag) {
13508                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
13509                res = ast_play_and_wait(chan, "vm-urgent-removed");
13510                strcpy(flag, "");
13511             } else {
13512                ast_play_and_wait(chan, "vm-sorry");
13513             }
13514             cmd = 0;
13515          } else {
13516             cmd = ast_play_and_wait(chan, "vm-sorry");
13517          }
13518          break;
13519       case '5':
13520       case '6':
13521       case '7':
13522       case '8':
13523       case '9':
13524       case '*':
13525       case '#':
13526          cmd = ast_play_and_wait(chan, "vm-sorry");
13527          break;
13528 #if 0 
13529 /*  XXX Commented out for the moment because of the dangers of deleting
13530     a message while recording (can put the message numbers out of sync) */
13531       case '*':
13532          /* Cancel recording, delete message, offer to take another message*/
13533          cmd = ast_play_and_wait(chan, "vm-deleted");
13534          cmd = ast_filedelete(tempfile, NULL);
13535          if (outsidecaller) {
13536             res = vm_exec(chan, NULL);
13537             return res;
13538          }
13539          else
13540             return 1;
13541 #endif
13542       case '0':
13543          if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13544             cmd = ast_play_and_wait(chan, "vm-sorry");
13545             break;
13546          }
13547          if (msg_exists || recorded) {
13548             cmd = ast_play_and_wait(chan, "vm-saveoper");
13549             if (!cmd)
13550                cmd = ast_waitfordigit(chan, 3000);
13551             if (cmd == '1') {
13552                ast_filerename(tempfile, recordfile, NULL);
13553                ast_play_and_wait(chan, "vm-msgsaved");
13554                cmd = '0';
13555             } else if (cmd == '4') {
13556                if (flag) {
13557                   ast_play_and_wait(chan, "vm-marked-urgent");
13558                   strcpy(flag, "Urgent");
13559                }
13560                ast_play_and_wait(chan, "vm-msgsaved");
13561                cmd = '0';
13562             } else {
13563                ast_play_and_wait(chan, "vm-deleted");
13564                DELETE(tempfile, -1, tempfile, vmu);
13565                cmd = '0';
13566             }
13567          }
13568          return cmd;
13569       default:
13570          /* If the caller is an ouside caller, and the review option is enabled,
13571             allow them to review the message, but let the owner of the box review
13572             their OGM's */
13573          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13574             return cmd;
13575          if (msg_exists) {
13576             cmd = ast_play_and_wait(chan, "vm-review");
13577             if (!cmd && outsidecaller) {
13578                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13579                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
13580                } else if (flag) {
13581                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13582                }
13583             }
13584          } else {
13585             cmd = ast_play_and_wait(chan, "vm-torerecord");
13586             if (!cmd)
13587                cmd = ast_waitfordigit(chan, 600);
13588          }
13589          
13590          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13591             cmd = ast_play_and_wait(chan, "vm-reachoper");
13592             if (!cmd)
13593                cmd = ast_waitfordigit(chan, 600);
13594          }
13595 #if 0
13596          if (!cmd)
13597             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13598 #endif
13599          if (!cmd)
13600             cmd = ast_waitfordigit(chan, 6000);
13601          if (!cmd) {
13602             attempts++;
13603          }
13604          if (attempts > max_attempts) {
13605             cmd = 't';
13606          }
13607       }
13608    }
13609    if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13610       /* Hang up or timeout, so delete the recording. */
13611       ast_filedelete(tempfile, NULL);
13612    }
13613 
13614    if (cmd != 't' && outsidecaller)
13615       ast_play_and_wait(chan, "vm-goodbye");
13616 
13617    return cmd;
13618 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11416 of file app_voicemail_imapstorage.c.

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

11417 {
11418    int new = 0, old = 0, urgent = 0;
11419 
11420    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11421 
11422    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11423       mwi_sub->old_urgent = urgent;
11424       mwi_sub->old_new = new;
11425       mwi_sub->old_old = old;
11426       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11427       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11428    }
11429 }

static void poll_subscribed_mailboxes ( void   )  [static]

Definition at line 11431 of file app_voicemail_imapstorage.c.

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

11432 {
11433    struct mwi_sub *mwi_sub;
11434 
11435    AST_RWLIST_RDLOCK(&mwi_subs);
11436    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11437       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11438          poll_subscribed_mailbox(mwi_sub);
11439       }
11440    }
11441    AST_RWLIST_UNLOCK(&mwi_subs);
11442 }

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.

Definition at line 1022 of file app_voicemail_imapstorage.c.

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::emailbody, ast_vm_user::emailsubject, ast_vm_user::exit, exitcontext, globalflags, ast_vm_user::locale, ast_vm_user::maxdeletedmsg, ast_vm_user::maxmsg, ast_vm_user::maxsecs, ast_vm_user::minsecs, ast_vm_user::passwordlocation, ast_vm_user::saydurationm, saydurationminfo, ast_vm_user::volgain, and ast_vm_user::zonetag.

01023 {
01024    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
01025    vmu->passwordlocation = passwordlocation;
01026    if (saydurationminfo) {
01027       vmu->saydurationm = saydurationminfo;
01028    }
01029    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
01030    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
01031    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
01032    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
01033    ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
01034    if (vmminsecs) {
01035       vmu->minsecs = vmminsecs;
01036    }
01037    if (vmmaxsecs) {
01038       vmu->maxsecs = vmmaxsecs;
01039    }
01040    if (maxmsg) {
01041       vmu->maxmsg = maxmsg;
01042    }
01043    if (maxdeletedmsg) {
01044       vmu->maxdeletedmsg = maxdeletedmsg;
01045    }
01046    vmu->volgain = volgain;
01047    ast_free(vmu->emailsubject);
01048    vmu->emailsubject = NULL;
01049    ast_free(vmu->emailbody);
01050    vmu->emailbody = NULL;
01051 #ifdef IMAP_STORAGE
01052    ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
01053 #endif
01054 }

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 4333 of file app_voicemail_imapstorage.c.

References ast_callerid_merge(), ast_callerid_split(), ast_config_destroy(), ast_config_load, ast_localtime(), ast_log(), ast_strdupa, ast_strftime_locale(), ast_strlen_zero(), ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, emaildateformat, ast_vm_user::fullname, ast_vm_user::locale, LOG_DEBUG, ast_vm_user::mailbox, make_dir(), make_file(), option_debug, pbx_builtin_setvar_helper(), and S_OR.

04334 {
04335    char callerid[256];
04336    char num[12];
04337    char fromdir[256], fromfile[256];
04338    struct ast_config *msg_cfg;
04339    const char *origcallerid, *origtime;
04340    char origcidname[80], origcidnum[80], origdate[80];
04341    int inttime;
04342    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04343 
04344    /* Prepare variables for substitution in email body and subject */
04345    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04346    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04347    snprintf(num, sizeof(num), "%d", msgnum);
04348    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04349    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04350    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04351    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04352       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04353    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04354    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04355    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04356    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04357    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04358 
04359    /* Retrieve info from VM attribute file */
04360    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04361    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04362    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04363       strcat(fromfile, ".txt");
04364    }
04365    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
04366       if (option_debug > 0) {
04367          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04368       }
04369       return;
04370    }
04371 
04372    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04373       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04374       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04375       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04376       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04377    }
04378 
04379    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04380       struct timeval tv = { inttime, };
04381       struct ast_tm tm;
04382       ast_localtime(&tv, &tm, NULL);
04383       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04384       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04385    }
04386    ast_config_destroy(msg_cfg);
04387 }

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

Definition at line 7003 of file app_voicemail_imapstorage.c.

References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_strdupa, ast_strlen_zero(), and strsep().

07004 {
07005    struct ast_event *event;
07006    char *mailbox, *context;
07007 
07008    /* Strip off @default */
07009    context = mailbox = ast_strdupa(box);
07010    strsep(&context, "@");
07011    if (ast_strlen_zero(context))
07012       context = "default";
07013 
07014    if (!(event = ast_event_new(AST_EVENT_MWI,
07015          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07016          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07017          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07018          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07019          AST_EVENT_IE_END))) {
07020       return;
07021    }
07022 
07023    ast_event_queue_and_cache(event);
07024 }

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

Definition at line 12509 of file app_voicemail_imapstorage.c.

References ast_config_load, ast_copy_string(), ast_log(), ast_variable_retrieve(), config_flags, and LOG_NOTICE.

12509                                                                                            {
12510    struct ast_config *pwconf;
12511    struct ast_flags config_flags = { 0 };
12512 
12513    pwconf = ast_config_load(secretfn, config_flags);
12514    if (pwconf) {
12515       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12516       if (val) {
12517          ast_copy_string(password, val, passwordlen);
12518          return;
12519       }
12520    }
12521    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12522 }

static int reload ( void   )  [static]

Definition at line 13030 of file app_voicemail_imapstorage.c.

References load_config().

13031 {
13032    return load_config(1);
13033 }

static void rename_file ( char *  sfn,
char *  dfn 
) [static]

Renames a message in a mailbox folder.

Parameters:
sfn The path to the mailbox information and data file to be renamed.
dfn The 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 4002 of file app_voicemail_imapstorage.c.

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

04003 {
04004    char stxt[PATH_MAX];
04005    char dtxt[PATH_MAX];
04006    ast_filerename(sfn, dfn, NULL);
04007    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04008    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04009    if (ast_check_realtime("voicemail_data")) {
04010       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04011    }
04012    rename(stxt, dtxt);
04013 }

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

Definition at line 6145 of file app_voicemail_imapstorage.c.

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

06146 {
06147    /* we know the actual number of messages, so stop process when number is hit */
06148 
06149    int x, dest;
06150    char sfn[PATH_MAX];
06151    char dfn[PATH_MAX];
06152 
06153    if (vm_lock_path(dir)) {
06154       return ERROR_LOCK_PATH;
06155    }
06156 
06157    for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06158       make_file(sfn, sizeof(sfn), dir, x);
06159       if (EXISTS(dir, x, sfn, NULL)) {
06160 
06161          if (x != dest) {
06162             make_file(dfn, sizeof(dfn), dir, dest);
06163             RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06164          }
06165 
06166          dest++;
06167       }
06168    }
06169    ast_unlock_path(dir);
06170 
06171    return dest;
06172 }

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 1488 of file app_voicemail_imapstorage.c.

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

01489 {
01490    /* This function could be made to generate one from a database, too */
01491    struct ast_vm_user *cur;
01492    int res = -1;
01493    AST_LIST_LOCK(&users);
01494    AST_LIST_TRAVERSE(&users, cur, list) {
01495       if ((!context || !strcasecmp(context, cur->context)) &&
01496          (!strcasecmp(mailbox, cur->mailbox)))
01497             break;
01498    }
01499    if (cur) {
01500       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01501       res = 0;
01502    }
01503    AST_LIST_UNLOCK(&users);
01504    return res;
01505 }

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

Definition at line 5518 of file app_voicemail_imapstorage.c.

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

05519 {
05520    char arguments[255];
05521    char ext_context[256] = "";
05522    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05523    struct ast_smdi_mwi_message *mwi_msg;
05524 
05525    if (!ast_strlen_zero(context))
05526       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05527    else
05528       ast_copy_string(ext_context, extension, sizeof(ext_context));
05529 
05530    if (smdi_iface) {
05531       if (ast_app_has_voicemail(ext_context, NULL)) 
05532          ast_smdi_mwi_set(smdi_iface, extension);
05533       else
05534          ast_smdi_mwi_unset(smdi_iface, extension);
05535 
05536       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05537          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05538          if (!strncmp(mwi_msg->cause, "INV", 3))
05539             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05540          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05541             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05542          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05543          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05544       } else {
05545          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05546       }
05547    }
05548 
05549    if (!ast_strlen_zero(externnotify)) {
05550       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05551          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05552       } else {
05553          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05554          ast_debug(1, "Executing %s\n", arguments);
05555          ast_safe_system(arguments);
05556       }
05557    }
05558 }

static int save_to_folder ( struct ast_vm_user vmu,
struct vm_state vms,
int  msg,
int  box 
) [static]

Definition at line 6182 of file app_voicemail_imapstorage.c.

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

06183 {
06184 #ifdef IMAP_STORAGE
06185    /* we must use mbox(x) folder names, and copy the message there */
06186    /* simple. huh? */
06187    char sequence[10];
06188    char mailbox[256];
06189    int res;
06190 
06191    /* get the real IMAP message number for this message */
06192    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06193    
06194    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06195    ast_mutex_lock(&vms->lock);
06196    /* if save to Old folder, put in INBOX as read */
06197    if (box == OLD_FOLDER) {
06198       mail_setflag(vms->mailstream, sequence, "\\Seen");
06199       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06200    } else if (box == NEW_FOLDER) {
06201       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06202       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06203    }
06204    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06205       ast_mutex_unlock(&vms->lock);
06206       return 0;
06207    }
06208    /* Create the folder if it don't exist */
06209    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06210    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06211    if (mail_create(vms->mailstream, mailbox) == NIL) 
06212       ast_debug(5, "Folder exists.\n");
06213    else
06214       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06215    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06216    ast_mutex_unlock(&vms->lock);
06217    return res;
06218 #else
06219    char *dir = vms->curdir;
06220    char *username = vms->username;
06221    char *context = vmu->context;
06222    char sfn[PATH_MAX];
06223    char dfn[PATH_MAX];
06224    char ddir[PATH_MAX];
06225    const char *dbox = mbox(vmu, box);
06226    int x, i;
06227    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06228 
06229    if (vm_lock_path(ddir))
06230       return ERROR_LOCK_PATH;
06231 
06232    x = last_message_index(vmu, ddir) + 1;
06233 
06234    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06235       x--;
06236       for (i = 1; i <= x; i++) {
06237          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06238          make_file(sfn, sizeof(sfn), ddir, i);
06239          make_file(dfn, sizeof(dfn), ddir, i - 1);
06240          if (EXISTS(ddir, i, sfn, NULL)) {
06241             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06242          } else
06243             break;
06244       }
06245    } else {
06246       if (x >= vmu->maxmsg) {
06247          ast_unlock_path(ddir);
06248          return -1;
06249       }
06250    }
06251    make_file(sfn, sizeof(sfn), dir, msg);
06252    make_file(dfn, sizeof(dfn), ddir, x);
06253    if (strcmp(sfn, dfn)) {
06254       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06255    }
06256    ast_unlock_path(ddir);
06257 #endif
06258    return 0;
06259 }

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

Definition at line 6175 of file app_voicemail_imapstorage.c.

References AST_DIGIT_ANY, and ast_say_number().

06176 {
06177    int d;
06178    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06179    return d;
06180 }

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

Definition at line 12495 of file app_voicemail_imapstorage.c.

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

12496 {
12497    int res = -1;
12498    char dir[PATH_MAX];
12499    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12500    ast_debug(2, "About to try retrieving name file %s\n", dir);
12501    RETRIEVE(dir, -1, mailbox, context);
12502    if (ast_fileexists(dir, NULL, NULL)) {
12503       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12504    }
12505    DISPOSE(dir, -1);
12506    return res;
12507 }

static int sendmail ( char *  srcemail,
struct ast_vm_user vmu,
int  msgnum,
char *  context,
char *  mailbox,
const char *  fromfolder,
char *  cidnum,
char *  cidname,
char *  attach,
char *  attach2,
char *  format,
int  duration,
int  attach_user_voicemail,
struct ast_channel chan,
const char *  category,
const char *  flag 
) [static]

Definition at line 4848 of file app_voicemail_imapstorage.c.

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

04849 {
04850    FILE *p = NULL;
04851    char tmp[80] = "/tmp/astmail-XXXXXX";
04852    char tmp2[256];
04853    char *stringp;
04854 
04855    if (vmu && ast_strlen_zero(vmu->email)) {
04856       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04857       return(0);
04858    }
04859 
04860    /* Mail only the first format */
04861    format = ast_strdupa(format);
04862    stringp = format;
04863    strsep(&stringp, "|");
04864 
04865    if (!strcmp(format, "wav49"))
04866       format = "WAV";
04867    ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
04868    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04869       command hangs */
04870    if ((p = vm_mkftemp(tmp)) == NULL) {
04871       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04872       return -1;
04873    } else {
04874       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04875       fclose(p);
04876       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04877       ast_safe_system(tmp2);
04878       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04879    }
04880    return 0;
04881 }

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 4883 of file app_voicemail_imapstorage.c.

References ast_channel_unref, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_log(), 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_locale(), ast_strlen_zero(), check_mime(), ENDL, ast_vm_user::fullname, ast_vm_user::locale, mailcmd, MAXHOSTNAMELEN, pagerbody, pagerdateformat, pagerfromstring, pagersubject, prep_email_sub_vars(), S_OR, strip_control_and_high(), vm_mkftemp(), and vmu_tm().

04884 {
04885    char enc_cidnum[256], enc_cidname[256];
04886    char date[256];
04887    char host[MAXHOSTNAMELEN] = "";
04888    char who[256];
04889    char dur[PATH_MAX];
04890    char tmp[80] = "/tmp/astmail-XXXXXX";
04891    char tmp2[PATH_MAX];
04892    struct ast_tm tm;
04893    FILE *p;
04894    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04895 
04896    if (!str1 || !str2) {
04897       ast_free(str1);
04898       ast_free(str2);
04899       return -1;
04900    }
04901 
04902    if (cidnum) {
04903       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04904    }
04905    if (cidname) {
04906       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04907    }
04908 
04909    if ((p = vm_mkftemp(tmp)) == NULL) {
04910       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04911       ast_free(str1);
04912       ast_free(str2);
04913       return -1;
04914    }
04915    gethostname(host, sizeof(host)-1);
04916    if (strchr(srcemail, '@')) {
04917       ast_copy_string(who, srcemail, sizeof(who));
04918    } else {
04919       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04920    }
04921    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04922    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04923    fprintf(p, "Date: %s\n", date);
04924 
04925    /* Reformat for custom pager format */
04926    ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04927 
04928    if (!ast_strlen_zero(pagerfromstring)) {
04929       struct ast_channel *ast;
04930       if ((ast = ast_dummy_channel_alloc())) {
04931          char *ptr;
04932          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04933          ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
04934 
04935          if (check_mime(ast_str_buffer(str1))) {
04936             int first_line = 1;
04937             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04938             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04939                *ptr = '\0';
04940                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04941                first_line = 0;
04942                /* Substring is smaller, so this will never grow */
04943                ast_str_set(&str2, 0, "%s", ptr + 1);
04944             }
04945             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04946          } else {
04947             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04948          }
04949          ast = ast_channel_unref(ast);
04950       } else {
04951          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04952       }
04953    } else {
04954       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04955    }
04956 
04957    if (check_mime(vmu->fullname)) {
04958       int first_line = 1;
04959       char *ptr;
04960       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
04961       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04962          *ptr = '\0';
04963          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04964          first_line = 0;
04965          /* Substring is smaller, so this will never grow */
04966          ast_str_set(&str2, 0, "%s", ptr + 1);
04967       }
04968       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
04969    } else {
04970       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
04971    }
04972 
04973    if (!ast_strlen_zero(pagersubject)) {
04974       struct ast_channel *ast;
04975       if ((ast = ast_dummy_channel_alloc())) {
04976          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04977          ast_str_substitute_variables(&str1, 0, ast, pagersubject);
04978          if (check_mime(ast_str_buffer(str1))) {
04979             int first_line = 1;
04980             char *ptr;
04981             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04982             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04983                *ptr = '\0';
04984                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04985                first_line = 0;
04986                /* Substring is smaller, so this will never grow */
04987                ast_str_set(&str2, 0, "%s", ptr + 1);
04988             }
04989             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04990          } else {
04991             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04992          }
04993          ast = ast_channel_unref(ast);
04994       } else {
04995          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04996       }
04997    } else {
04998       if (ast_strlen_zero(flag)) {
04999          fprintf(p, "Subject: New VM\n\n");
05000       } else {
05001          fprintf(p, "Subject: New %s VM\n\n", flag);
05002       }
05003    }
05004 
05005    if (pagerbody) {
05006       struct ast_channel *ast;
05007       if ((ast = ast_dummy_channel_alloc())) {
05008          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
05009          ast_str_substitute_variables(&str1, 0, ast, pagerbody);
05010          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
05011          ast = ast_channel_unref(ast);
05012       } else {
05013          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
05014       }
05015    } else {
05016       fprintf(p, "New %s long %s msg in box %s\n"
05017             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
05018    }
05019 
05020    fclose(p);
05021    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
05022    ast_safe_system(tmp2);
05023    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
05024    ast_free(str1);
05025    ast_free(str2);
05026    return 0;
05027 }

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

Definition at line 11073 of file app_voicemail_imapstorage.c.

References ast_category_browse(), ast_cli(), ast_config_destroy(), ast_load_realtime_multientry(), ast_variable_browse(), CLI_FAILURE, CLI_SUCCESS, SENTINEL, and var.

11074 {
11075    struct ast_config *cfg;
11076    const char *cat = NULL;
11077 
11078    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11079       "context", context, SENTINEL))) {
11080       return CLI_FAILURE;
11081    }
11082 
11083    ast_cli(fd,
11084       "\n"
11085       "=============================================================\n"
11086       "=== Configured Voicemail Users ==============================\n"
11087       "=============================================================\n"
11088       "===\n");
11089 
11090    while ((cat = ast_category_browse(cfg, cat))) {
11091       struct ast_variable *var = NULL;
11092       ast_cli(fd,
11093          "=== Mailbox ...\n"
11094          "===\n");
11095       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11096          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11097       ast_cli(fd,
11098          "===\n"
11099          "=== ---------------------------------------------------------\n"
11100          "===\n");
11101    }
11102 
11103    ast_cli(fd,
11104       "=============================================================\n"
11105       "\n");
11106 
11107    ast_config_destroy(cfg);
11108 
11109    return CLI_SUCCESS;
11110 }

static void start_poll_thread ( void   )  [static]

Definition at line 11568 of file app_voicemail_imapstorage.c.

References AST_EVENT_IE_END, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_report_subs(), AST_EVENT_SUB, ast_event_subscribe(), AST_EVENT_UNSUB, ast_pthread_create, mb_poll_thread(), mwi_sub_event_cb(), mwi_sub_sub, mwi_unsub_event_cb(), mwi_unsub_sub, poll_thread, and poll_thread_run.

static void stop_poll_thread ( void   )  [static]

Definition at line 11586 of file app_voicemail_imapstorage.c.

References ast_cond_signal, ast_event_unsubscribe(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, mwi_sub_sub, mwi_unsub_sub, poll_cond, poll_lock, poll_thread, and poll_thread_run.

11587 {
11588    poll_thread_run = 0;
11589 
11590    if (mwi_sub_sub) {
11591       ast_event_unsubscribe(mwi_sub_sub);
11592       mwi_sub_sub = NULL;
11593    }
11594 
11595    if (mwi_unsub_sub) {
11596       ast_event_unsubscribe(mwi_unsub_sub);
11597       mwi_unsub_sub = NULL;
11598    }
11599 
11600    ast_mutex_lock(&poll_lock);
11601    ast_cond_signal(&poll_cond);
11602    ast_mutex_unlock(&poll_lock);
11603 
11604    pthread_join(poll_thread, NULL);
11605 
11606    poll_thread = AST_PTHREADT_NULL;
11607 }

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 992 of file app_voicemail_imapstorage.c.

00993 {
00994    char *bufptr = buf;
00995    for (; *input; input++) {
00996       if (*input < 32) {
00997          continue;
00998       }
00999       *bufptr++ = *input;
01000       if (bufptr == buf + buflen - 1) {
01001          break;
01002       }
01003    }
01004    *bufptr = '\0';
01005    return buf;
01006 }

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

Definition at line 11732 of file app_voicemail_imapstorage.c.

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

11733 {
11734    char *current;
11735 
11736    /* Add 16 for fudge factor */
11737    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11738 
11739    ast_str_reset(str);
11740    
11741    /* Substitute strings \r, \n, and \t into the appropriate characters */
11742    for (current = (char *) value; *current; current++) {
11743       if (*current == '\\') {
11744          current++;
11745          if (!*current) {
11746             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11747             break;
11748          }
11749          switch (*current) {
11750          case '\\':
11751             ast_str_append(&str, 0, "\\");
11752             break;
11753          case 'r':
11754             ast_str_append(&str, 0, "\r");
11755             break;
11756          case 'n':
11757 #ifdef IMAP_STORAGE
11758             if (!str->used || str->str[str->used - 1] != '\r') {
11759                ast_str_append(&str, 0, "\r");
11760             }
11761 #endif
11762             ast_str_append(&str, 0, "\n");
11763             break;
11764          case 't':
11765             ast_str_append(&str, 0, "\t");
11766             break;
11767          default:
11768             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11769             break;
11770          }
11771       } else {
11772          ast_str_append(&str, 0, "%c", *current);
11773       }
11774    }
11775 
11776    return ast_str_buffer(str);
11777 }

static int unload_module ( void   )  [static]

Definition at line 13035 of file app_voicemail_imapstorage.c.

References ao2_ref, app, app2, app3, app4, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_manager_unregister(), AST_PTHREADT_NULL, ast_taskprocessor_unreference(), AST_TEST_UNREGISTER, ast_uninstall_vm_functions(), ast_unload_realtime(), ast_unregister_application(), cli_voicemail, free_vm_users(), free_vm_zones(), inprocess_container, mailbox_exists_acf, mwi_subscription_tps, poll_thread, sayname_app, and stop_poll_thread().

13036 {
13037    int res;
13038 
13039    res = ast_unregister_application(app);
13040    res |= ast_unregister_application(app2);
13041    res |= ast_unregister_application(app3);
13042    res |= ast_unregister_application(app4);
13043    res |= ast_unregister_application(sayname_app);
13044    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13045    res |= ast_manager_unregister("VoicemailUsersList");
13046    res |= ast_data_unregister(NULL);
13047 #ifdef TEST_FRAMEWORK
13048    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13049    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13050    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13051    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13052    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13053 #endif
13054    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13055    ast_uninstall_vm_functions();
13056    ao2_ref(inprocess_container, -1);
13057 
13058    if (poll_thread != AST_PTHREADT_NULL)
13059       stop_poll_thread();
13060 
13061    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13062    ast_unload_realtime("voicemail");
13063    ast_unload_realtime("voicemail_data");
13064 
13065    free_vm_users();
13066    free_vm_zones();
13067    return res;
13068 }

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

Definition at line 1758 of file app_voicemail_imapstorage.c.

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

01758                                                                                         {
01759 
01760    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01761    if (!vms->dh_arraysize) {
01762       /* initial allocation */
01763       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01764          return -1;
01765       }
01766       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01767          return -1;
01768       }
01769       vms->dh_arraysize = arraysize;
01770    } else if (vms->dh_arraysize < arraysize) {
01771       if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
01772          return -1;
01773       }
01774       if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
01775          return -1;
01776       }
01777       memset(vms->deleted, 0, arraysize * sizeof(int));
01778       memset(vms->heard, 0, arraysize * sizeof(int));
01779       vms->dh_arraysize = arraysize;
01780    }
01781 
01782    return 0;
01783 }

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 9735 of file app_voicemail_imapstorage.c.

References adsi_begin(), adsi_login(), adsi_password(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_readstring(), ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_test_suite_event_notify, ast_verb, ast_waitstream(), find_user(), ast_vm_user::password, S_COR, and vm_password.

09738 {
09739    int useadsi = 0, valid = 0, logretries = 0;
09740    char password[AST_MAX_EXTENSION]="", *passptr;
09741    struct ast_vm_user vmus, *vmu = NULL;
09742 
09743    /* If ADSI is supported, setup login screen */
09744    adsi_begin(chan, &useadsi);
09745    if (!skipuser && useadsi)
09746       adsi_login(chan);
09747    ast_test_suite_event_notify("PLAYBACK", "Message: vm-login");
09748    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09749       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09750       return -1;
09751    }
09752 
09753    /* Authenticate them and get their mailbox/password */
09754 
09755    while (!valid && (logretries < max_logins)) {
09756       /* Prompt for, and read in the username */
09757       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09758          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09759          return -1;
09760       }
09761       if (ast_strlen_zero(mailbox)) {
09762          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09763             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09764          } else {
09765             ast_verb(3, "Username not entered\n"); 
09766             return -1;
09767          }
09768       } else if (mailbox[0] == '*') {
09769          /* user entered '*' */
09770          ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
09771          if (ast_exists_extension(chan, chan->context, "a", 1,
09772             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09773             return -1;
09774          }
09775          ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
09776          mailbox[0] = '\0';
09777       }
09778 
09779       if (useadsi)
09780          adsi_password(chan);
09781 
09782       if (!ast_strlen_zero(prefix)) {
09783          char fullusername[80] = "";
09784          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09785          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09786          ast_copy_string(mailbox, fullusername, mailbox_size);
09787       }
09788 
09789       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09790       vmu = find_user(&vmus, context, mailbox);
09791       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09792          /* saved password is blank, so don't bother asking */
09793          password[0] = '\0';
09794       } else {
09795          ast_test_suite_event_notify("PLAYBACK", "Message: %s", vm_password);
09796          if (ast_streamfile(chan, vm_password, chan->language)) {
09797             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09798             return -1;
09799          }
09800          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09801             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09802             return -1;
09803          } else if (password[0] == '*') {
09804             /* user entered '*' */
09805             ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
09806             if (ast_exists_extension(chan, chan->context, "a", 1,
09807                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09808                mailbox[0] = '*';
09809                return -1;
09810             }
09811             ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
09812             mailbox[0] = '\0';
09813             /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
09814             vmu = NULL;
09815          }
09816       }
09817 
09818       if (vmu) {
09819          passptr = vmu->password;
09820          if (passptr[0] == '-') passptr++;
09821       }
09822       if (vmu && !strcmp(passptr, password))
09823          valid++;
09824       else {
09825          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09826          if (!ast_strlen_zero(prefix))
09827             mailbox[0] = '\0';
09828       }
09829       logretries++;
09830       if (!valid) {
09831          if (skipuser || logretries >= max_logins) {
09832             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect");
09833             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09834                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09835                return -1;
09836             }
09837          } else {
09838             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect-mailbox");
09839             if (useadsi)
09840                adsi_login(chan);
09841             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09842                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09843                return -1;
09844             }
09845          }
09846          if (ast_waitstream(chan, "")) /* Channel is hung up */
09847             return -1;
09848       }
09849    }
09850    if (!valid && (logretries >= max_logins)) {
09851       ast_stopstream(chan);
09852       ast_play_and_wait(chan, "vm-goodbye");
09853       return -1;
09854    }
09855    if (vmu && !skipuser) {
09856       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09857    }
09858    return 0;
09859 }

static int vm_box_exists ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 10968 of file app_voicemail_imapstorage.c.

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

10969 {
10970    struct ast_vm_user svm;
10971    char *context, *box;
10972    AST_DECLARE_APP_ARGS(args,
10973       AST_APP_ARG(mbox);
10974       AST_APP_ARG(options);
10975    );
10976    static int dep_warning = 0;
10977 
10978    if (ast_strlen_zero(data)) {
10979       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
10980       return -1;
10981    }
10982 
10983    if (!dep_warning) {
10984       dep_warning = 1;
10985       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
10986    }
10987 
10988    box = ast_strdupa(data);
10989 
10990    AST_STANDARD_APP_ARGS(args, box);
10991 
10992    if (args.options) {
10993    }
10994 
10995    if ((context = strchr(args.mbox, '@'))) {
10996       *context = '\0';
10997       context++;
10998    }
10999 
11000    if (find_user(&svm, context, args.mbox)) {
11001       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
11002    } else
11003       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
11004 
11005    return 0;
11006 }

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:
chan The channel for the current user. We read the language property from this.
vms passed into the language-specific vm_browse_messages function.
vmu passed 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 9714 of file app_voicemail_imapstorage.c.

References ast_channel::language, vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_he(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_browse_messages_vi(), and vm_browse_messages_zh().

09715 {
09716    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09717       return vm_browse_messages_es(chan, vms, vmu);
09718    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09719       return vm_browse_messages_gr(chan, vms, vmu);
09720    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09721       return vm_browse_messages_he(chan, vms, vmu);
09722    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09723       return vm_browse_messages_it(chan, vms, vmu);
09724    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09725       return vm_browse_messages_pt(chan, vms, vmu);
09726    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09727       return vm_browse_messages_vi(chan, vms, vmu);
09728    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09729       return vm_browse_messages_zh(chan, vms, vmu);
09730    } else {                                             /* Default to English syntax */
09731       return vm_browse_messages_en(chan, vms, vmu);
09732    }
09733 }

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 9553 of file app_voicemail_imapstorage.c.

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

09554 {
09555    int cmd = 0;
09556 
09557    if (vms->lastmsg > -1) {
09558       cmd = play_message(chan, vmu, vms);
09559    } else {
09560       cmd = ast_play_and_wait(chan, "vm-youhave");
09561       if (!cmd) 
09562          cmd = ast_play_and_wait(chan, "vm-no");
09563       if (!cmd) {
09564          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09565          cmd = ast_play_and_wait(chan, vms->fn);
09566       }
09567       if (!cmd)
09568          cmd = ast_play_and_wait(chan, "vm-messages");
09569    }
09570    return cmd;
09571 }

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 9607 of file app_voicemail_imapstorage.c.

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

09608 {
09609    int cmd;
09610 
09611    if (vms->lastmsg > -1) {
09612       cmd = play_message(chan, vmu, vms);
09613    } else {
09614       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09615       if (!cmd)
09616          cmd = ast_play_and_wait(chan, "vm-messages");
09617       if (!cmd) {
09618          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09619          cmd = ast_play_and_wait(chan, vms->fn);
09620       }
09621    }
09622    return cmd;
09623 }

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 9501 of file app_voicemail_imapstorage.c.

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

09502 {
09503    int cmd = 0;
09504 
09505    if (vms->lastmsg > -1) {
09506       cmd = play_message(chan, vmu, vms);
09507    } else {
09508       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09509       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09510          if (!cmd) {
09511             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09512             cmd = ast_play_and_wait(chan, vms->fn);
09513          }
09514          if (!cmd)
09515             cmd = ast_play_and_wait(chan, "vm-messages");
09516       } else {
09517          if (!cmd)
09518             cmd = ast_play_and_wait(chan, "vm-messages");
09519          if (!cmd) {
09520             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09521             cmd = ast_play_and_wait(chan, vms->fn);
09522          }
09523       }
09524    } 
09525    return cmd;
09526 }

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

Definition at line 9529 of file app_voicemail_imapstorage.c.

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

09530 {
09531    int cmd = 0;
09532 
09533    if (vms->lastmsg > -1) {
09534       cmd = play_message(chan, vmu, vms);
09535    } else {
09536       if (!strcasecmp(vms->fn, "INBOX")) {
09537          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09538       } else {
09539          cmd = ast_play_and_wait(chan, "vm-nomessages");
09540       }
09541    }
09542    return cmd;
09543 }

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 9581 of file app_voicemail_imapstorage.c.

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

09582 {
09583    int cmd;
09584 
09585    if (vms->lastmsg > -1) {
09586       cmd = play_message(chan, vmu, vms);
09587    } else {
09588       cmd = ast_play_and_wait(chan, "vm-no");
09589       if (!cmd)
09590          cmd = ast_play_and_wait(chan, "vm-message");
09591       if (!cmd) {
09592          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09593          cmd = ast_play_and_wait(chan, vms->fn);
09594       }
09595    }
09596    return cmd;
09597 }

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 9633 of file app_voicemail_imapstorage.c.

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

09634 {
09635    int cmd;
09636 
09637    if (vms->lastmsg > -1) {
09638       cmd = play_message(chan, vmu, vms);
09639    } else {
09640       cmd = ast_play_and_wait(chan, "vm-no");
09641       if (!cmd) {
09642          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09643          cmd = ast_play_and_wait(chan, vms->fn);
09644       }
09645       if (!cmd)
09646          cmd = ast_play_and_wait(chan, "vm-messages");
09647    }
09648    return cmd;
09649 }

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 9687 of file app_voicemail_imapstorage.c.

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

09688 {
09689    int cmd = 0;
09690 
09691    if (vms->lastmsg > -1) {
09692       cmd = play_message(chan, vmu, vms);
09693    } else {
09694       cmd = ast_play_and_wait(chan, "vm-no");
09695       if (!cmd) {
09696          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09697          cmd = ast_play_and_wait(chan, vms->fn);
09698       }
09699    }
09700    return cmd;
09701 }

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 9659 of file app_voicemail_imapstorage.c.

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

09660 {
09661    int cmd;
09662 
09663    if (vms->lastmsg > -1) {
09664       cmd = play_message(chan, vmu, vms);
09665    } else {
09666       cmd = ast_play_and_wait(chan, "vm-you");
09667       if (!cmd) 
09668          cmd = ast_play_and_wait(chan, "vm-haveno");
09669       if (!cmd)
09670          cmd = ast_play_and_wait(chan, "vm-messages");
09671       if (!cmd) {
09672          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09673          cmd = ast_play_and_wait(chan, vms->fn);
09674       }
09675    }
09676    return cmd;
09677 }

static void vm_change_password ( struct ast_vm_user vmu,
const char *  newpassword 
) [static]

The handler for the change password option.

Parameters:
vmu The voicemail user to work with.
newpassword The 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 1514 of file app_voicemail_imapstorage.c.

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

01515 {
01516    struct ast_config   *cfg = NULL;
01517    struct ast_variable *var = NULL;
01518    struct ast_category *cat = NULL;
01519    char *category = NULL, *value = NULL, *new = NULL;
01520    const char *tmp = NULL;
01521    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01522    char secretfn[PATH_MAX] = "";
01523    int found = 0;
01524 
01525    if (!change_password_realtime(vmu, newpassword))
01526       return;
01527 
01528    /* check if we should store the secret in the spool directory next to the messages */
01529    switch (vmu->passwordlocation) {
01530    case OPT_PWLOC_SPOOLDIR:
01531       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
01532       if (write_password_to_file(secretfn, newpassword) == 0) {
01533          ast_test_suite_event_notify("PASSWORDCHANGED", "Message: secret.conf updated with new password\r\nPasswordSource: secret.conf");
01534          ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
01535          reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01536          ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01537          break;
01538       } else {
01539          ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
01540       }
01541       /* Fall-through */
01542    case OPT_PWLOC_VOICEMAILCONF:
01543       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01544          while ((category = ast_category_browse(cfg, category))) {
01545             if (!strcasecmp(category, vmu->context)) {
01546                if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01547                   ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01548                   break;
01549                }
01550                value = strstr(tmp, ",");
01551                if (!value) {
01552                   new = alloca(strlen(newpassword)+1);
01553                   sprintf(new, "%s", newpassword);
01554                } else {
01555                   new = alloca((strlen(value) + strlen(newpassword) + 1));
01556                   sprintf(new, "%s%s", newpassword, value);
01557                }
01558                if (!(cat = ast_category_get(cfg, category))) {
01559                   ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01560                   break;
01561                }
01562                ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01563                found = 1;
01564             }
01565          }
01566          /* save the results */
01567          if (found) {
01568             ast_test_suite_event_notify("PASSWORDCHANGED", "Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
01569             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01570             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01571             ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01572             break;
01573          }
01574       }
01575       /* Fall-through */
01576    case OPT_PWLOC_USERSCONF:
01577       /* check users.conf and update the password stored for the mailbox */
01578       /* if no vmsecret entry exists create one. */
01579       if ((cfg = ast_config_load("users.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01580          ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01581          for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
01582             ast_debug(4, "users.conf: %s\n", category);
01583             if (!strcasecmp(category, vmu->mailbox)) {
01584                if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01585                   ast_debug(3, "looks like we need to make vmsecret!\n");
01586                   var = ast_variable_new("vmsecret", newpassword, "");
01587                } else {
01588                   var = NULL;
01589                }
01590                new = alloca(strlen(newpassword) + 1);
01591                sprintf(new, "%s", newpassword);
01592                if (!(cat = ast_category_get(cfg, category))) {
01593                   ast_debug(4, "failed to get category!\n");
01594                   ast_free(var);
01595                   break;
01596                }
01597                if (!var) {
01598                   ast_variable_update(cat, "vmsecret", new, NULL, 0);
01599                } else {
01600                   ast_variable_append(cat, var);
01601                }
01602                found = 1;
01603                break;
01604             }
01605          }
01606          /* save the results and clean things up */
01607          if (found) {
01608             ast_test_suite_event_notify("PASSWORDCHANGED", "Message: users.conf updated with new password\r\nPasswordSource: users.conf");
01609             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01610             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01611             ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
01612          }
01613       }
01614    }
01615 }

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

Definition at line 1617 of file app_voicemail_imapstorage.c.

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

01618 {
01619    char buf[255];
01620    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01621    ast_debug(1, "External password: %s\n",buf);
01622    if (!ast_safe_system(buf)) {
01623       ast_test_suite_event_notify("PASSWORDCHANGED", "Message: external script updated with new password\r\nPasswordSource: external");
01624       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01625       /* Reset the password in memory, too */
01626       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01627    }
01628 }

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

Definition at line 1189 of file app_voicemail_imapstorage.c.

References AST_APP_ARG, ast_close_fds_above_n(), AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_safe_fork(), ast_strdupa, errno, and LOG_WARNING.

01190 {
01191    int fds[2], pid = 0;
01192 
01193    memset(buf, 0, len);
01194 
01195    if (pipe(fds)) {
01196       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01197    } else {
01198       /* good to go*/
01199       pid = ast_safe_fork(0);
01200 
01201       if (pid < 0) {
01202          /* ok maybe not */
01203          close(fds[0]);
01204          close(fds[1]);
01205          snprintf(buf, len, "FAILURE: Fork failed");
01206       } else if (pid) {
01207          /* parent */
01208          close(fds[1]);
01209          if (read(fds[0], buf, len) < 0) {
01210             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01211          }
01212          close(fds[0]);
01213       } else {
01214          /*  child */
01215          AST_DECLARE_APP_ARGS(arg,
01216             AST_APP_ARG(v)[20];
01217          );
01218          char *mycmd = ast_strdupa(command);
01219 
01220          close(fds[0]);
01221          dup2(fds[1], STDOUT_FILENO);
01222          close(fds[1]);
01223          ast_close_fds_above_n(STDOUT_FILENO);
01224 
01225          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01226 
01227          execv(arg.v[0], arg.v); 
01228          printf("FAILURE: %s", strerror(errno));
01229          _exit(0);
01230       }
01231    }
01232    return buf;
01233 }

static int vm_delete ( char *  file  )  [static]

Removes the voicemail sound and information file.

Parameters:
file The path to the sound file. This will be the the folder and message index, without the extension.
This is used by the DELETE macro when voicemails are stored on the file system.

Returns:
zero on success, -1 on error.

Definition at line 4187 of file app_voicemail_imapstorage.c.

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

04188 {
04189    char *txt;
04190    int txtsize = 0;
04191 
04192    txtsize = (strlen(file) + 5)*sizeof(char);
04193    txt = alloca(txtsize);
04194    /* Sprintf here would safe because we alloca'd exactly the right length,
04195     * but trying to eliminate all sprintf's anyhow
04196     */
04197    if (ast_check_realtime("voicemail_data")) {
04198       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04199    }
04200    snprintf(txt, txtsize, "%s.txt", file);
04201    unlink(txt);
04202    return ast_filedelete(file, NULL);
04203 }

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

Definition at line 10627 of file app_voicemail_imapstorage.c.

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

10628 {
10629    int res = 0;
10630    char *tmp;
10631    struct leave_vm_options leave_options;
10632    struct ast_flags flags = { 0 };
10633    char *opts[OPT_ARG_ARRAY_SIZE];
10634    AST_DECLARE_APP_ARGS(args,
10635       AST_APP_ARG(argv0);
10636       AST_APP_ARG(argv1);
10637    );
10638    
10639    memset(&leave_options, 0, sizeof(leave_options));
10640 
10641    if (chan->_state != AST_STATE_UP)
10642       ast_answer(chan);
10643 
10644    if (!ast_strlen_zero(data)) {
10645       tmp = ast_strdupa(data);
10646       AST_STANDARD_APP_ARGS(args, tmp);
10647       if (args.argc == 2) {
10648          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10649             return -1;
10650          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10651          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10652             int gain;
10653 
10654             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10655                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10656                return -1;
10657             } else {
10658                leave_options.record_gain = (signed char) gain;
10659             }
10660          }
10661          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10662             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10663                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10664          }
10665       }
10666    } else {
10667       char temp[256];
10668       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10669       if (res < 0)
10670          return res;
10671       if (ast_strlen_zero(temp))
10672          return 0;
10673       args.argv0 = ast_strdupa(temp);
10674    }
10675 
10676    res = leave_voicemail(chan, args.argv0, &leave_options);
10677    if (res == 't') {
10678       ast_play_and_wait(chan, "vm-goodbye");
10679       res = 0;
10680    }
10681 
10682    if (res == OPERATOR_EXIT) {
10683       res = 0;
10684    }
10685 
10686    if (res == ERROR_LOCK_PATH) {
10687       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10688       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10689       res = 0;
10690    }
10691 
10692    return res;
10693 }

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

Definition at line 9861 of file app_voicemail_imapstorage.c.

References ast_channel::_state, adsi_begin(), adsi_delete(), adsi_folders(), adsi_goodbye(), adsi_message(), adsi_status(), adsi_status2(), advanced_options(), args, ast_adsi_unload_session(), ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_goto_if_exists(), ast_log(), AST_LOG_ERROR, ast_manager_event, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_test_suite_assert, ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), ast_vm_user::callback, close_mailbox(), ast_vm_user::context, ast_channel::context, dialout(), ast_vm_user::dialout, ERROR_LOCK_PATH, EVENT_FLAG_CALL, find_user(), ast_flags::flags, forward_message(), free_user(), get_folder2(), get_folder_by_name(), globalflags, has_voicemail(), language, ast_vm_user::language, ast_vm_user::mailbox, make_file(), maxlogins, ast_vm_user::maxmsg, mbox(), NEW_FOLDER, OLD_FOLDER, open_mailbox(), OPERATOR_EXIT, OPT_ARG_ARRAY_SIZE, OPT_ARG_PLAYFOLDER, OPT_ARG_RECORDGAIN, OPT_AUTOPLAY, OPT_PREPEND_MAILBOX, OPT_RECORDGAIN, OPT_SILENT, parse(), ast_vm_user::password, play_message(), queue_mwi_event(), run_externnotify(), save_to_folder(), say_and_wait(), vm_app_options, vm_authenticate(), vm_browse_messages(), VM_FORCEGREET, VM_FORCENAME, vm_instructions(), vm_intro(), VM_MESSAGEWRAP, vm_newuser(), vm_options(), vm_play_folder_name(), VM_SKIPAFTERCMD, VM_SVMAIL, and vmfmts.

09862 {
09863    /* XXX This is, admittedly, some pretty horrendous code.  For some
09864       reason it just seemed a lot easier to do with GOTO's.  I feel
09865       like I'm back in my GWBASIC days. XXX */
09866    int res = -1;
09867    int cmd = 0;
09868    int valid = 0;
09869    char prefixstr[80] ="";
09870    char ext_context[256]="";
09871    int box;
09872    int useadsi = 0;
09873    int skipuser = 0;
09874    struct vm_state vms;
09875    struct ast_vm_user *vmu = NULL, vmus;
09876    char *context = NULL;
09877    int silentexit = 0;
09878    struct ast_flags flags = { 0 };
09879    signed char record_gain = 0;
09880    int play_auto = 0;
09881    int play_folder = 0;
09882    int in_urgent = 0;
09883 #ifdef IMAP_STORAGE
09884    int deleted = 0;
09885 #endif
09886 
09887    /* Add the vm_state to the active list and keep it active */
09888    memset(&vms, 0, sizeof(vms));
09889 
09890    vms.lastmsg = -1;
09891 
09892    memset(&vmus, 0, sizeof(vmus));
09893 
09894    ast_test_suite_event_notify("START", "Message: vm_execmain started");
09895    if (chan->_state != AST_STATE_UP) {
09896       ast_debug(1, "Before ast_answer\n");
09897       ast_answer(chan);
09898    }
09899 
09900    if (!ast_strlen_zero(data)) {
09901       char *opts[OPT_ARG_ARRAY_SIZE];
09902       char *parse;
09903       AST_DECLARE_APP_ARGS(args,
09904          AST_APP_ARG(argv0);
09905          AST_APP_ARG(argv1);
09906       );
09907 
09908       parse = ast_strdupa(data);
09909 
09910       AST_STANDARD_APP_ARGS(args, parse);
09911 
09912       if (args.argc == 2) {
09913          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09914             return -1;
09915          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09916             int gain;
09917             if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
09918                if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09919                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09920                   return -1;
09921                } else {
09922                   record_gain = (signed char) gain;
09923                }
09924             } else {
09925                ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
09926             }
09927          }
09928          if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
09929             play_auto = 1;
09930             if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
09931                /* See if it is a folder name first */
09932                if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
09933                   if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
09934                      play_folder = -1;
09935                   }
09936                } else {
09937                   play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
09938                }
09939             } else {
09940                ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
09941             }
09942             if (play_folder > 9 || play_folder < 0) {
09943                ast_log(AST_LOG_WARNING,
09944                   "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
09945                   opts[OPT_ARG_PLAYFOLDER]);
09946                play_folder = 0;
09947             }
09948          }
09949       } else {
09950          /* old style options parsing */
09951          while (*(args.argv0)) {
09952             if (*(args.argv0) == 's')
09953                ast_set_flag(&flags, OPT_SILENT);
09954             else if (*(args.argv0) == 'p')
09955                ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
09956             else 
09957                break;
09958             (args.argv0)++;
09959          }
09960 
09961       }
09962 
09963       valid = ast_test_flag(&flags, OPT_SILENT);
09964 
09965       if ((context = strchr(args.argv0, '@')))
09966          *context++ = '\0';
09967 
09968       if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
09969          ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
09970       else
09971          ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
09972 
09973       if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
09974          skipuser++;
09975       else
09976          valid = 0;
09977    }
09978 
09979    if (!valid)
09980       res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
09981 
09982    ast_debug(1, "After vm_authenticate\n");
09983 
09984    if (vms.username[0] == '*') {
09985       ast_debug(1, "user pressed * in context '%s'\n", chan->context);
09986 
09987       /* user entered '*' */
09988       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
09989          ast_test_suite_event_notify("REDIRECT", "Message: redirecting user to 'a' extension");
09990          res = 0; /* prevent hangup */
09991          goto out;
09992       }
09993    }
09994 
09995    if (!res) {
09996       valid = 1;
09997       if (!skipuser)
09998          vmu = &vmus;
09999    } else {
10000       res = 0;
10001    }
10002 
10003    /* If ADSI is supported, setup login screen */
10004    adsi_begin(chan, &useadsi);
10005 
10006    ast_test_suite_assert(valid);
10007    if (!valid) {
10008       goto out;
10009    }
10010    ast_test_suite_event_notify("AUTHENTICATED", "Message: vm_user authenticated");
10011 
10012 #ifdef IMAP_STORAGE
10013    pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
10014    pthread_setspecific(ts_vmstate.key, &vms);
10015 
10016    vms.interactive = 1;
10017    vms.updated = 1;
10018    if (vmu)
10019       ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
10020    vmstate_insert(&vms);
10021    init_vm_state(&vms);
10022 #endif
10023    /* Avoid allocating a buffer of 0 bytes, because some platforms really don't like that. */
10024    if (!(vms.deleted = ast_calloc(vmu->maxmsg ? vmu->maxmsg : 1, sizeof(int)))) {
10025       ast_log(AST_LOG_ERROR, "Could not allocate memory for deleted message storage!\n");
10026       cmd = ast_play_and_wait(chan, "an-error-has-occured");
10027       return -1;
10028    }
10029    if (!(vms.heard = ast_calloc(vmu->maxmsg ? vmu->maxmsg : 1, sizeof(int)))) {
10030       ast_log(AST_LOG_ERROR, "Could not allocate memory for heard message storage!\n");
10031       cmd = ast_play_and_wait(chan, "an-error-has-occured");
10032       return -1;
10033    }
10034    
10035    /* Set language from config to override channel language */
10036    if (!ast_strlen_zero(vmu->language))
10037       ast_string_field_set(chan, language, vmu->language);
10038 
10039    /* Retrieve urgent, old and new message counts */
10040    ast_debug(1, "Before open_mailbox\n");
10041    res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
10042    if (res < 0)
10043       goto out;
10044    vms.oldmessages = vms.lastmsg + 1;
10045    ast_debug(1, "Number of old messages: %d\n", vms.oldmessages);
10046    /* check INBOX */
10047    res = open_mailbox(&vms, vmu, NEW_FOLDER);
10048    if (res < 0)
10049       goto out;
10050    vms.newmessages = vms.lastmsg + 1;
10051    ast_debug(1, "Number of new messages: %d\n", vms.newmessages);
10052    /* Start in Urgent */
10053    in_urgent = 1;
10054    res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
10055    if (res < 0)
10056       goto out;
10057    vms.urgentmessages = vms.lastmsg + 1;
10058    ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages);
10059 
10060    /* Select proper mailbox FIRST!! */
10061    if (play_auto) {
10062       ast_test_suite_event_notify("AUTOPLAY", "Message: auto-playing messages");
10063       if (vms.urgentmessages) {
10064          in_urgent = 1;
10065          res = open_mailbox(&vms, vmu, 11);
10066       } else {
10067          in_urgent = 0;
10068          res = open_mailbox(&vms, vmu, play_folder);
10069       }
10070       if (res < 0)
10071          goto out;
10072 
10073       /* If there are no new messages, inform the user and hangup */
10074       if (vms.lastmsg == -1) {
10075          in_urgent = 0;
10076          cmd = vm_browse_messages(chan, &vms, vmu);
10077          res = 0;
10078          goto out;
10079       }
10080    } else {
10081       if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
10082          /* If we only have old messages start here */
10083          res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
10084          in_urgent = 0;
10085          play_folder = 1;
10086          if (res < 0)
10087             goto out;
10088       } else if (!vms.urgentmessages && vms.newmessages) {
10089          /* If we have new messages but none are urgent */
10090          in_urgent = 0;
10091          res = open_mailbox(&vms, vmu, NEW_FOLDER);
10092          if (res < 0)
10093             goto out;
10094       }
10095    }
10096 
10097    if (useadsi)
10098       adsi_status(chan, &vms);
10099    res = 0;
10100 
10101    /* Check to see if this is a new user */
10102    if (!strcasecmp(vmu->mailbox, vmu->password) && 
10103       (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
10104       if (ast_play_and_wait(chan, "vm-newuser") == -1)
10105          ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
10106       cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
10107       if ((cmd == 't') || (cmd == '#')) {
10108          /* Timeout */
10109          ast_test_suite_event_notify("TIMEOUT", "Message: response from user timed out");
10110          res = 0;
10111          goto out;
10112       } else if (cmd < 0) {
10113          /* Hangup */
10114          ast_test_suite_event_notify("HANGUP", "Message: hangup detected");
10115          res = -1;
10116          goto out;
10117       }
10118    }
10119 #ifdef IMAP_STORAGE
10120       ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
10121       if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
10122          ast_debug(1, "*** QUOTA EXCEEDED!!\n");
10123          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10124       }
10125       ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
10126       if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
10127          ast_log(AST_LOG_WARNING, "No more messages possible.  User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
10128          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10129       }
10130 #endif
10131 
10132    ast_test_suite_event_notify("INTRO", "Message: playing intro menu");
10133    if (play_auto) {
10134       cmd = '1';
10135    } else {
10136       cmd = vm_intro(chan, vmu, &vms);
10137    }
10138    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10139 
10140    vms.repeats = 0;
10141    vms.starting = 1;
10142    while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
10143       /* Run main menu */
10144       switch (cmd) {
10145       case '1': /* First message */
10146          vms.curmsg = 0;
10147          /* Fall through */
10148       case '5': /* Play current message */
10149          ast_test_suite_event_notify("BROWSE", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
10150          cmd = vm_browse_messages(chan, &vms, vmu);
10151          break;
10152       case '2': /* Change folders */
10153          ast_test_suite_event_notify("CHANGEFOLDER", "Message: browsing to a different folder");
10154          if (useadsi)
10155             adsi_folders(chan, 0, "Change to folder...");
10156 
10157          cmd = get_folder2(chan, "vm-changeto", 0);
10158          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10159          if (cmd == '#') {
10160             cmd = 0;
10161          } else if (cmd > 0) {
10162             cmd = cmd - '0';
10163             res = close_mailbox(&vms, vmu);
10164             if (res == ERROR_LOCK_PATH)
10165                goto out;
10166             /* If folder is not urgent, set in_urgent to zero! */
10167             if (cmd != 11) in_urgent = 0;
10168             res = open_mailbox(&vms, vmu, cmd);
10169             if (res < 0)
10170                goto out;
10171             play_folder = cmd;
10172             cmd = 0;
10173          }
10174          if (useadsi)
10175             adsi_status2(chan, &vms);
10176 
10177          if (!cmd) {
10178             cmd = vm_play_folder_name(chan, vms.vmbox);
10179          }
10180 
10181          vms.starting = 1;
10182          break;
10183       case '3': /* Advanced options */
10184          ast_test_suite_event_notify("ADVOPTIONS", "Message: entering advanced options menu");
10185          cmd = 0;
10186          vms.repeats = 0;
10187          while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
10188             switch (cmd) {
10189             case '1': /* Reply */
10190                if (vms.lastmsg > -1 && !vms.starting) {
10191                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
10192                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
10193                      res = cmd;
10194                      goto out;
10195                   }
10196                } else {
10197                   cmd = ast_play_and_wait(chan, "vm-sorry");
10198                }
10199                cmd = 't';
10200                break;
10201             case '2': /* Callback */
10202                if (!vms.starting)
10203                   ast_verb(3, "Callback Requested\n");
10204                if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
10205                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
10206                   if (cmd == 9) {
10207                      silentexit = 1;
10208                      goto out;
10209                   } else if (cmd == ERROR_LOCK_PATH) {
10210                      res = cmd;
10211                      goto out;
10212                   }
10213                } else {
10214                   cmd = ast_play_and_wait(chan, "vm-sorry");
10215                }
10216                cmd = 't';
10217                break;
10218             case '3': /* Envelope */
10219                if (vms.lastmsg > -1 && !vms.starting) {
10220                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
10221                   if (cmd == ERROR_LOCK_PATH) {
10222                      res = cmd;
10223                      goto out;
10224                   }
10225                } else {
10226                   cmd = ast_play_and_wait(chan, "vm-sorry");
10227                }
10228                cmd = 't';
10229                break;
10230             case '4': /* Dialout */
10231                if (!ast_strlen_zero(vmu->dialout)) {
10232                   cmd = dialout(chan, vmu, NULL, vmu->dialout);
10233                   if (cmd == 9) {
10234                      silentexit = 1;
10235                      goto out;
10236                   }
10237                } else {
10238                   cmd = ast_play_and_wait(chan, "vm-sorry");
10239                }
10240                cmd = 't';
10241                break;
10242 
10243             case '5': /* Leave VoiceMail */
10244                if (ast_test_flag(vmu, VM_SVMAIL)) {
10245                   cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
10246                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
10247                      res = cmd;
10248                      goto out;
10249                   }
10250                } else {
10251                   cmd = ast_play_and_wait(chan, "vm-sorry");
10252                }
10253                cmd = 't';
10254                break;
10255 
10256             case '*': /* Return to main menu */
10257                cmd = 't';
10258                break;
10259 
10260             default:
10261                cmd = 0;
10262                if (!vms.starting) {
10263                   cmd = ast_play_and_wait(chan, "vm-toreply");
10264                }
10265                if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
10266                   cmd = ast_play_and_wait(chan, "vm-tocallback");
10267                }
10268                if (!cmd && !vms.starting) {
10269                   cmd = ast_play_and_wait(chan, "vm-tohearenv");
10270                }
10271                if (!ast_strlen_zero(vmu->dialout) && !cmd) {
10272                   cmd = ast_play_and_wait(chan, "vm-tomakecall");
10273                }
10274                if (ast_test_flag(vmu, VM_SVMAIL) && !cmd) {
10275                   cmd = ast_play_and_wait(chan, "vm-leavemsg");
10276                }
10277                if (!cmd) {
10278                   cmd = ast_play_and_wait(chan, "vm-starmain");
10279                }
10280                if (!cmd) {
10281                   cmd = ast_waitfordigit(chan, 6000);
10282                }
10283                if (!cmd) {
10284                   vms.repeats++;
10285                }
10286                if (vms.repeats > 3) {
10287                   cmd = 't';
10288                }
10289                ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10290             }
10291          }
10292          if (cmd == 't') {
10293             cmd = 0;
10294             vms.repeats = 0;
10295          }
10296          break;
10297       case '4': /* Go to the previous message */
10298          ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg - 1, vms.curmsg - 1);
10299          if (vms.curmsg > 0) {
10300             vms.curmsg--;
10301             cmd = play_message(chan, vmu, &vms);
10302          } else {
10303             /* Check if we were listening to new
10304                messages.  If so, go to Urgent messages
10305                instead of saying "no more messages"
10306             */
10307             if (in_urgent == 0 && vms.urgentmessages > 0) {
10308                /* Check for Urgent messages */
10309                in_urgent = 1;
10310                res = close_mailbox(&vms, vmu);
10311                if (res == ERROR_LOCK_PATH)
10312                   goto out;
10313                res = open_mailbox(&vms, vmu, 11);  /* Open Urgent folder */
10314                if (res < 0)
10315                   goto out;
10316                ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
10317                vms.curmsg = vms.lastmsg;
10318                if (vms.lastmsg < 0) {
10319                   cmd = ast_play_and_wait(chan, "vm-nomore");
10320                }
10321             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10322                vms.curmsg = vms.lastmsg;
10323                cmd = play_message(chan, vmu, &vms);
10324             } else {
10325                cmd = ast_play_and_wait(chan, "vm-nomore");
10326             }
10327          }
10328          break;
10329       case '6': /* Go to the next message */
10330          ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg + 1, vms.curmsg + 1);
10331          if (vms.curmsg < vms.lastmsg) {
10332             vms.curmsg++;
10333             cmd = play_message(chan, vmu, &vms);
10334          } else {
10335             if (in_urgent && vms.newmessages > 0) {
10336                /* Check if we were listening to urgent
10337                 * messages.  If so, go to regular new messages
10338                 * instead of saying "no more messages"
10339                 */
10340                in_urgent = 0;
10341                res = close_mailbox(&vms, vmu);
10342                if (res == ERROR_LOCK_PATH)
10343                   goto out;
10344                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10345                if (res < 0)
10346                   goto out;
10347                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10348                vms.curmsg = -1;
10349                if (vms.lastmsg < 0) {
10350                   cmd = ast_play_and_wait(chan, "vm-nomore");
10351                }
10352             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10353                vms.curmsg = 0;
10354                cmd = play_message(chan, vmu, &vms);
10355             } else {
10356                cmd = ast_play_and_wait(chan, "vm-nomore");
10357             }
10358          }
10359          break;
10360       case '7': /* Delete the current message */
10361          if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
10362             vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
10363             if (useadsi)
10364                adsi_delete(chan, &vms);
10365             if (vms.deleted[vms.curmsg]) {
10366                if (play_folder == 0) {
10367                   if (in_urgent) {
10368                      vms.urgentmessages--;
10369                   } else {
10370                      vms.newmessages--;
10371                   }
10372                }
10373                else if (play_folder == 1)
10374                   vms.oldmessages--;
10375                cmd = ast_play_and_wait(chan, "vm-deleted");
10376             } else {
10377                if (play_folder == 0) {
10378                   if (in_urgent) {
10379                      vms.urgentmessages++;
10380                   } else {
10381                      vms.newmessages++;
10382                   }
10383                }
10384                else if (play_folder == 1)
10385                   vms.oldmessages++;
10386                cmd = ast_play_and_wait(chan, "vm-undeleted");
10387             }
10388             if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10389                if (vms.curmsg < vms.lastmsg) {
10390                   vms.curmsg++;
10391                   cmd = play_message(chan, vmu, &vms);
10392                } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10393                   vms.curmsg = 0;
10394                   cmd = play_message(chan, vmu, &vms);
10395                } else {
10396                   /* Check if we were listening to urgent
10397                      messages.  If so, go to regular new messages
10398                      instead of saying "no more messages"
10399                   */
10400                   if (in_urgent == 1) {
10401                      /* Check for new messages */
10402                      in_urgent = 0;
10403                      res = close_mailbox(&vms, vmu);
10404                      if (res == ERROR_LOCK_PATH)
10405                         goto out;
10406                      res = open_mailbox(&vms, vmu, NEW_FOLDER);
10407                      if (res < 0)
10408                         goto out;
10409                      ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10410                      vms.curmsg = -1;
10411                      if (vms.lastmsg < 0) {
10412                         cmd = ast_play_and_wait(chan, "vm-nomore");
10413                      }
10414                   } else {
10415                      cmd = ast_play_and_wait(chan, "vm-nomore");
10416                   }
10417                }
10418             }
10419          } else /* Delete not valid if we haven't selected a message */
10420             cmd = 0;
10421 #ifdef IMAP_STORAGE
10422          deleted = 1;
10423 #endif
10424          break;
10425    
10426       case '8': /* Forward the current message */
10427          if (vms.lastmsg > -1) {
10428             cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
10429             if (cmd == ERROR_LOCK_PATH) {
10430                res = cmd;
10431                goto out;
10432             }
10433          } else {
10434             /* Check if we were listening to urgent
10435                messages.  If so, go to regular new messages
10436                instead of saying "no more messages"
10437             */
10438             if (in_urgent == 1 && vms.newmessages > 0) {
10439                /* Check for new messages */
10440                in_urgent = 0;
10441                res = close_mailbox(&vms, vmu);
10442                if (res == ERROR_LOCK_PATH)
10443                   goto out;
10444                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10445                if (res < 0)
10446                   goto out;
10447                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10448                vms.curmsg = -1;
10449                if (vms.lastmsg < 0) {
10450                   cmd = ast_play_and_wait(chan, "vm-nomore");
10451                }
10452             } else {
10453                cmd = ast_play_and_wait(chan, "vm-nomore");
10454             }
10455          }
10456          break;
10457       case '9': /* Save message to folder */
10458          ast_test_suite_event_notify("SAVEMSG", "Message: saving message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg);
10459          if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
10460             /* No message selected */
10461             cmd = 0;
10462             break;
10463          }
10464          if (useadsi)
10465             adsi_folders(chan, 1, "Save to folder...");
10466          cmd = get_folder2(chan, "vm-savefolder", 1);
10467          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
10468          box = 0; /* Shut up compiler */
10469          if (cmd == '#') {
10470             cmd = 0;
10471             break;
10472          } else if (cmd > 0) {
10473             box = cmd = cmd - '0';
10474             cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
10475             if (cmd == ERROR_LOCK_PATH) {
10476                res = cmd;
10477                goto out;
10478 #ifndef IMAP_STORAGE
10479             } else if (!cmd) {
10480                vms.deleted[vms.curmsg] = 1;
10481 #endif
10482             } else {
10483                vms.deleted[vms.curmsg] = 0;
10484                vms.heard[vms.curmsg] = 0;
10485             }
10486          }
10487          make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
10488          if (useadsi)
10489             adsi_message(chan, &vms);
10490          snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
10491          if (!cmd) {
10492             cmd = ast_play_and_wait(chan, "vm-message");
10493             if (!cmd) 
10494                cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
10495             if (!cmd)
10496                cmd = ast_play_and_wait(chan, "vm-savedto");
10497             if (!cmd)
10498                cmd = vm_play_folder_name(chan, vms.fn);
10499          } else {
10500             cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10501          }
10502          if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
10503             if (vms.curmsg < vms.lastmsg) {
10504                vms.curmsg++;
10505                cmd = play_message(chan, vmu, &vms);
10506             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10507                vms.curmsg = 0;
10508                cmd = play_message(chan, vmu, &vms);
10509             } else {
10510                /* Check if we were listening to urgent
10511                   messages.  If so, go to regular new messages
10512                   instead of saying "no more messages"
10513                */
10514                if (in_urgent == 1 && vms.newmessages > 0) {
10515                   /* Check for new messages */
10516                   in_urgent = 0;
10517                   res = close_mailbox(&vms, vmu);
10518                   if (res == ERROR_LOCK_PATH)
10519                      goto out;
10520                   res = open_mailbox(&vms, vmu, NEW_FOLDER);
10521                   if (res < 0)
10522                      goto out;
10523                   ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10524                   vms.curmsg = -1;
10525                   if (vms.lastmsg < 0) {
10526                      cmd = ast_play_and_wait(chan, "vm-nomore");
10527                   }
10528                } else {
10529                   cmd = ast_play_and_wait(chan, "vm-nomore");
10530                }
10531             }
10532          }
10533          break;
10534       case '*': /* Help */
10535          if (!vms.starting) {
10536             cmd = ast_play_and_wait(chan, "vm-onefor");
10537             if (!strncasecmp(chan->language, "he", 2)) {
10538                cmd = ast_play_and_wait(chan, "vm-for");
10539             }
10540             if (!cmd)
10541                cmd = vm_play_folder_name(chan, vms.vmbox);
10542             if (!cmd)
10543                cmd = ast_play_and_wait(chan, "vm-opts");
10544             if (!cmd)
10545                cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
10546          } else
10547             cmd = 0;
10548          break;
10549       case '0': /* Mailbox options */
10550          cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
10551          if (useadsi)
10552             adsi_status(chan, &vms);
10553          break;
10554       default: /* Nothing */
10555          ast_test_suite_event_notify("PLAYBACK", "Message: instructions");
10556          cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
10557          break;
10558       }
10559    }
10560    if ((cmd == 't') || (cmd == '#')) {
10561       /* Timeout */
10562       res = 0;
10563    } else {
10564       /* Hangup */
10565       res = -1;
10566    }
10567 
10568 out:
10569    if (res > -1) {
10570       ast_stopstream(chan);
10571       adsi_goodbye(chan);
10572       if (valid && res != OPERATOR_EXIT) {
10573          if (silentexit)
10574             res = ast_play_and_wait(chan, "vm-dialout");
10575          else 
10576             res = ast_play_and_wait(chan, "vm-goodbye");
10577       }
10578       if ((valid && res > 0) || res == OPERATOR_EXIT) {
10579          res = 0;
10580       }
10581       if (useadsi)
10582          ast_adsi_unload_session(chan);
10583    }
10584    if (vmu)
10585       close_mailbox(&vms, vmu);
10586    if (valid) {
10587       int new = 0, old = 0, urgent = 0;
10588       snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
10589       ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
10590       /* Urgent flag not passwd to externnotify here */
10591       run_externnotify(vmu->context, vmu->mailbox, NULL);
10592       ast_app_inboxcount2(ext_context, &urgent, &new, &old);
10593       queue_mwi_event(ext_context, urgent, new, old);
10594    }
10595 #ifdef IMAP_STORAGE
10596    /* expunge message - use UID Expunge if supported on IMAP server*/
10597    ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
10598    if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
10599       ast_mutex_lock(&vms.lock);
10600 #ifdef HAVE_IMAP_TK2006
10601       if (LEVELUIDPLUS (vms.mailstream)) {
10602          mail_expunge_full(vms.mailstream, NIL, EX_UID);
10603       } else 
10604 #endif
10605          mail_expunge(vms.mailstream);
10606       ast_mutex_unlock(&vms.lock);
10607    }
10608    /*  before we delete the state, we should copy pertinent info
10609     *  back to the persistent model */
10610    if (vmu) {
10611       vmstate_delete(&vms);
10612    }
10613 #endif
10614    if (vmu)
10615       free_user(vmu);
10616    if (vms.deleted)
10617       ast_free(vms.deleted);
10618    if (vms.heard)
10619       ast_free(vms.heard);
10620 
10621 #ifdef IMAP_STORAGE
10622    pthread_setspecific(ts_vmstate.key, NULL);
10623 #endif
10624    return res;
10625 }

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 6850 of file app_voicemail_imapstorage.c.

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

06852 {
06853    int cmd = 0;
06854    int retries = 0, prepend_duration = 0, already_recorded = 0;
06855    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06856    char textfile[PATH_MAX];
06857    struct ast_config *msg_cfg;
06858    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06859 #ifndef IMAP_STORAGE
06860    signed char zero_gain = 0;
06861 #endif
06862    const char *duration_str;
06863 
06864    /* Must always populate duration correctly */
06865    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06866    strcpy(textfile, msgfile);
06867    strcpy(backup, msgfile);
06868    strcpy(backup_textfile, msgfile);
06869    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06870    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06871    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06872 
06873    if ((msg_cfg = ast_config_load(textfile, config_flags)) && msg_cfg != CONFIG_STATUS_FILEINVALID && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06874       *duration = atoi(duration_str);
06875    } else {
06876       *duration = 0;
06877    }
06878 
06879    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06880       if (cmd)
06881          retries = 0;
06882       switch (cmd) {
06883       case '1': 
06884 
06885 #ifdef IMAP_STORAGE
06886          /* Record new intro file */
06887          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06888          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06889          ast_play_and_wait(chan, INTRO);
06890          ast_play_and_wait(chan, "beep");
06891          play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, NULL, record_gain, vms, flag);
06892          cmd = 't';
06893 #else
06894 
06895          /* prepend a message to the current message, update the metadata and return */
06896 
06897          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06898          strcpy(textfile, msgfile);
06899          strncat(textfile, ".txt", sizeof(textfile) - 1);
06900          *duration = 0;
06901 
06902          /* if we can't read the message metadata, stop now */
06903          if (!msg_cfg) {
06904             cmd = 0;
06905             break;
06906          }
06907 
06908          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06909 #ifndef IMAP_STORAGE
06910          if (already_recorded) {
06911             ast_filecopy(backup, msgfile, NULL);
06912             copy(backup_textfile, textfile);
06913          }
06914          else {
06915             ast_filecopy(msgfile, backup, NULL);
06916             copy(textfile, backup_textfile);
06917          }
06918 #endif
06919          already_recorded = 1;
06920 
06921          if (record_gain)
06922             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06923 
06924          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
06925 
06926          if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */
06927             ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */
06928             ast_stream_and_wait(chan, vm_prepend_timeout, "");
06929             ast_filerename(backup, msgfile, NULL);
06930          }
06931 
06932          if (record_gain)
06933             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06934 
06935          
06936          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06937             *duration = atoi(duration_str);
06938 
06939          if (prepend_duration) {
06940             struct ast_category *msg_cat;
06941             /* need enough space for a maximum-length message duration */
06942             char duration_buf[12];
06943 
06944             *duration += prepend_duration;
06945             msg_cat = ast_category_get(msg_cfg, "message");
06946             snprintf(duration_buf, 11, "%ld", *duration);
06947             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06948                ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
06949             }
06950          }
06951 
06952 #endif
06953          break;
06954       case '2': 
06955          /* NULL out introfile so we know there is no intro! */
06956 #ifdef IMAP_STORAGE
06957          *vms->introfn = '\0';
06958 #endif
06959          cmd = 't';
06960          break;
06961       case '*':
06962          cmd = '*';
06963          break;
06964       default: 
06965          /* If time_out and return to menu, reset already_recorded */
06966          already_recorded = 0;
06967 
06968          cmd = ast_play_and_wait(chan, "vm-forwardoptions");
06969             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06970          if (!cmd) {
06971             cmd = ast_play_and_wait(chan, "vm-starmain");
06972             /* "press star to return to the main menu" */
06973          }
06974          if (!cmd) {
06975             cmd = ast_waitfordigit(chan, 6000);
06976          }
06977          if (!cmd) {
06978             retries++;
06979          }
06980          if (retries > 3) {
06981             cmd = '*'; /* Let's cancel this beast */
06982          }
06983          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
06984       }
06985    }
06986 
06987    if (msg_cfg)
06988       ast_config_destroy(msg_cfg);
06989    if (prepend_duration)
06990       *duration = prepend_duration;
06991 
06992    if (already_recorded && cmd == -1) {
06993       /* restore original message if prepention cancelled */
06994       ast_filerename(backup, msgfile, NULL);
06995       rename(backup_textfile, textfile);
06996    }
06997 
06998    if (cmd == 't' || cmd == 'S') /* XXX entering this block with a value of 'S' is probably no longer possible. */
06999       cmd = 0;
07000    return cmd;
07001 }

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

Definition at line 9179 of file app_voicemail_imapstorage.c.

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

09180 {
09181    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09182       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09183    } else {             /* Default to ENGLISH */
09184       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09185    }
09186 }

static int vm_instructions_en ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
) [static]

Definition at line 9078 of file app_voicemail_imapstorage.c.

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

09079 {
09080    int res = 0;
09081    /* Play instructions and wait for new command */
09082    while (!res) {
09083       if (vms->starting) {
09084          if (vms->lastmsg > -1) {
09085             if (skipadvanced)
09086                res = ast_play_and_wait(chan, "vm-onefor-full");
09087             else
09088                res = ast_play_and_wait(chan, "vm-onefor");
09089             if (!res)
09090                res = vm_play_folder_name(chan, vms->vmbox);
09091          }
09092          if (!res) {
09093             if (skipadvanced)
09094                res = ast_play_and_wait(chan, "vm-opts-full");
09095             else
09096                res = ast_play_and_wait(chan, "vm-opts");
09097          }
09098       } else {
09099          /* Added for additional help */
09100          if (skipadvanced) {
09101             res = ast_play_and_wait(chan, "vm-onefor-full");
09102             if (!res)
09103                res = vm_play_folder_name(chan, vms->vmbox);
09104             res = ast_play_and_wait(chan, "vm-opts-full");
09105          }
09106          /* Logic:
09107           * If the current message is not the first OR
09108           * if we're listening to the first new message and there are
09109           * also urgent messages, then prompt for navigation to the
09110           * previous message
09111           */
09112          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09113             res = ast_play_and_wait(chan, "vm-prev");
09114          }
09115          if (!res && !skipadvanced)
09116             res = ast_play_and_wait(chan, "vm-advopts");
09117          if (!res)
09118             res = ast_play_and_wait(chan, "vm-repeat");
09119          /* Logic:
09120           * If we're not listening to the last message OR
09121           * we're listening to the last urgent message and there are
09122           * also new non-urgent messages, then prompt for navigation
09123           * to the next message
09124           */
09125          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09126             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09127             res = ast_play_and_wait(chan, "vm-next");
09128          }
09129          if (!res) {
09130             if (!vms->deleted[vms->curmsg])
09131                res = ast_play_and_wait(chan, "vm-delete");
09132             else
09133                res = ast_play_and_wait(chan, "vm-undelete");
09134             if (!res)
09135                res = ast_play_and_wait(chan, "vm-toforward");
09136             if (!res)
09137                res = ast_play_and_wait(chan, "vm-savemessage");
09138          }
09139       }
09140       if (!res) {
09141          res = ast_play_and_wait(chan, "vm-helpexit");
09142       }
09143       if (!res)
09144          res = ast_waitfordigit(chan, 6000);
09145       if (!res) {
09146          vms->repeats++;
09147          if (vms->repeats > 2) {
09148             res = 't';
09149          }
09150       }
09151    }
09152    return res;
09153 }

static int vm_instructions_zh ( struct ast_channel chan,
struct ast_vm_user vmu,
struct vm_state vms,
int  skipadvanced,
int  in_urgent 
) [static]

Definition at line 9155 of file app_voicemail_imapstorage.c.

References ast_play_and_wait(), vm_state::lastmsg, vm_state::starting, vm_instructions_en(), vm_play_folder_name(), and vm_state::vmbox.

09156 {
09157    int res = 0;
09158    /* Play instructions and wait for new command */
09159    while (!res) {
09160       if (vms->lastmsg > -1) {
09161          res = ast_play_and_wait(chan, "vm-listen");
09162          if (!res)
09163             res = vm_play_folder_name(chan, vms->vmbox);
09164          if (!res)
09165             res = ast_play_and_wait(chan, "press");
09166          if (!res)
09167             res = ast_play_and_wait(chan, "digits/1");
09168       }
09169       if (!res)
09170          res = ast_play_and_wait(chan, "vm-opts");
09171       if (!res) {
09172          vms->starting = 0;
09173          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09174       }
09175    }
09176    return res;
09177 }

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

Definition at line 9016 of file app_voicemail_imapstorage.c.

References ast_fileexists(), ast_log(), ast_play_and_wait(), ast_test_flag, ast_vm_user::context, DISPOSE, ast_channel::language, LOG_WARNING, ast_vm_user::mailbox, RETRIEVE, vm_state::username, vm_intro_cs(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_gr(), vm_intro_he(), vm_intro_it(), vm_intro_multilang(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_pt(), vm_intro_pt_BR(), vm_intro_se(), vm_intro_vi(), vm_intro_zh(), VM_SPOOL_DIR, and VM_TEMPGREETWARN.

09017 {
09018    char prefile[256];
09019    
09020    /* Notify the user that the temp greeting is set and give them the option to remove it */
09021    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09022    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
09023       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09024       if (ast_fileexists(prefile, NULL, NULL) > 0) {
09025          ast_play_and_wait(chan, "vm-tempgreetactive");
09026       }
09027       DISPOSE(prefile, -1);
09028    }
09029 
09030    /* Play voicemail intro - syntax is different for different languages */
09031    if (0) {
09032       return 0;
09033    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
09034       return vm_intro_cs(chan, vms);
09035    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
09036       static int deprecation_warning = 0;
09037       if (deprecation_warning++ % 10 == 0) {
09038          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09039       }
09040       return vm_intro_cs(chan, vms);
09041    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
09042       return vm_intro_de(chan, vms);
09043    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
09044       return vm_intro_es(chan, vms);
09045    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
09046       return vm_intro_fr(chan, vms);
09047    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
09048       return vm_intro_gr(chan, vms);
09049    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
09050       return vm_intro_he(chan, vms);
09051    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
09052       return vm_intro_it(chan, vms);
09053    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
09054       return vm_intro_nl(chan, vms);
09055    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
09056       return vm_intro_no(chan, vms);
09057    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
09058       return vm_intro_pl(chan, vms);
09059    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09060       return vm_intro_pt_BR(chan, vms);
09061    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
09062       return vm_intro_pt(chan, vms);
09063    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
09064       return vm_intro_multilang(chan, vms, "n");
09065    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
09066       return vm_intro_se(chan, vms);
09067    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
09068       return vm_intro_multilang(chan, vms, "n");
09069    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
09070       return vm_intro_vi(chan, vms);
09071    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09072       return vm_intro_zh(chan, vms);
09073    } else {                                             /* Default to ENGLISH */
09074       return vm_intro_en(chan, vms);
09075    }
09076 }

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

Definition at line 8886 of file app_voicemail_imapstorage.c.

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

08887 {
08888    int res;
08889    res = ast_play_and_wait(chan, "vm-youhave");
08890    if (!res) {
08891       if (vms->newmessages) {
08892          if (vms->newmessages == 1) {
08893             res = ast_play_and_wait(chan, "digits/jednu");
08894          } else {
08895             res = say_and_wait(chan, vms->newmessages, chan->language);
08896          }
08897          if (!res) {
08898             if ((vms->newmessages == 1))
08899                res = ast_play_and_wait(chan, "vm-novou");
08900             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08901                res = ast_play_and_wait(chan, "vm-nove");
08902             if (vms->newmessages > 4)
08903                res = ast_play_and_wait(chan, "vm-novych");
08904          }
08905          if (vms->oldmessages && !res)
08906             res = ast_play_and_wait(chan, "vm-and");
08907          else if (!res) {
08908             if ((vms->newmessages == 1))
08909                res = ast_play_and_wait(chan, "vm-zpravu");
08910             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08911                res = ast_play_and_wait(chan, "vm-zpravy");
08912             if (vms->newmessages > 4)
08913                res = ast_play_and_wait(chan, "vm-zprav");
08914          }
08915       }
08916       if (!res && vms->oldmessages) {
08917          res = say_and_wait(chan, vms->oldmessages, chan->language);
08918          if (!res) {
08919             if ((vms->oldmessages == 1))
08920                res = ast_play_and_wait(chan, "vm-starou");
08921             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08922                res = ast_play_and_wait(chan, "vm-stare");
08923             if (vms->oldmessages > 4)
08924                res = ast_play_and_wait(chan, "vm-starych");
08925          }
08926          if (!res) {
08927             if ((vms->oldmessages == 1))
08928                res = ast_play_and_wait(chan, "vm-zpravu");
08929             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08930                res = ast_play_and_wait(chan, "vm-zpravy");
08931             if (vms->oldmessages > 4)
08932                res = ast_play_and_wait(chan, "vm-zprav");
08933          }
08934       }
08935       if (!res) {
08936          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08937             res = ast_play_and_wait(chan, "vm-no");
08938             if (!res)
08939                res = ast_play_and_wait(chan, "vm-zpravy");
08940          }
08941       }
08942    }
08943    return res;
08944 }

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

Definition at line 8582 of file app_voicemail_imapstorage.c.

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

08583 {
08584    /* Introduce messages they have */
08585    int res;
08586    res = ast_play_and_wait(chan, "vm-youhave");
08587    if (!res) {
08588       if (vms->newmessages) {
08589          if ((vms->newmessages == 1))
08590             res = ast_play_and_wait(chan, "digits/1F");
08591          else
08592             res = say_and_wait(chan, vms->newmessages, chan->language);
08593          if (!res)
08594             res = ast_play_and_wait(chan, "vm-INBOX");
08595          if (vms->oldmessages && !res)
08596             res = ast_play_and_wait(chan, "vm-and");
08597          else if (!res) {
08598             if ((vms->newmessages == 1))
08599                res = ast_play_and_wait(chan, "vm-message");
08600             else
08601                res = ast_play_and_wait(chan, "vm-messages");
08602          }
08603             
08604       }
08605       if (!res && vms->oldmessages) {
08606          if (vms->oldmessages == 1)
08607             res = ast_play_and_wait(chan, "digits/1F");
08608          else
08609             res = say_and_wait(chan, vms->oldmessages, chan->language);
08610          if (!res)
08611             res = ast_play_and_wait(chan, "vm-Old");
08612          if (!res) {
08613             if (vms->oldmessages == 1)
08614                res = ast_play_and_wait(chan, "vm-message");
08615             else
08616                res = ast_play_and_wait(chan, "vm-messages");
08617          }
08618       }
08619       if (!res) {
08620          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08621             res = ast_play_and_wait(chan, "vm-no");
08622             if (!res)
08623                res = ast_play_and_wait(chan, "vm-messages");
08624          }
08625       }
08626    }
08627    return res;
08628 }

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

Definition at line 8331 of file app_voicemail_imapstorage.c.

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

08332 {
08333    int res;
08334 
08335    /* Introduce messages they have */
08336    res = ast_play_and_wait(chan, "vm-youhave");
08337    if (!res) {
08338       if (vms->urgentmessages) {
08339          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08340          if (!res)
08341             res = ast_play_and_wait(chan, "vm-Urgent");
08342          if ((vms->oldmessages || vms->newmessages) && !res) {
08343             res = ast_play_and_wait(chan, "vm-and");
08344          } else if (!res) {
08345             if ((vms->urgentmessages == 1))
08346                res = ast_play_and_wait(chan, "vm-message");
08347             else
08348                res = ast_play_and_wait(chan, "vm-messages");
08349          }
08350       }
08351       if (vms->newmessages) {
08352          res = say_and_wait(chan, vms->newmessages, chan->language);
08353          if (!res)
08354             res = ast_play_and_wait(chan, "vm-INBOX");
08355          if (vms->oldmessages && !res)
08356             res = ast_play_and_wait(chan, "vm-and");
08357          else if (!res) {
08358             if ((vms->newmessages == 1))
08359                res = ast_play_and_wait(chan, "vm-message");
08360             else
08361                res = ast_play_and_wait(chan, "vm-messages");
08362          }
08363             
08364       }
08365       if (!res && vms->oldmessages) {
08366          res = say_and_wait(chan, vms->oldmessages, chan->language);
08367          if (!res)
08368             res = ast_play_and_wait(chan, "vm-Old");
08369          if (!res) {
08370             if (vms->oldmessages == 1)
08371                res = ast_play_and_wait(chan, "vm-message");
08372             else
08373                res = ast_play_and_wait(chan, "vm-messages");
08374          }
08375       }
08376       if (!res) {
08377          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08378             res = ast_play_and_wait(chan, "vm-no");
08379             if (!res)
08380                res = ast_play_and_wait(chan, "vm-messages");
08381          }
08382       }
08383    }
08384    return res;
08385 }

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

Definition at line 8631 of file app_voicemail_imapstorage.c.

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

08632 {
08633    /* Introduce messages they have */
08634    int res;
08635    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08636       res = ast_play_and_wait(chan, "vm-youhaveno");
08637       if (!res)
08638          res = ast_play_and_wait(chan, "vm-messages");
08639    } else {
08640       res = ast_play_and_wait(chan, "vm-youhave");
08641    }
08642    if (!res) {
08643       if (vms->newmessages) {
08644          if (!res) {
08645             if ((vms->newmessages == 1)) {
08646                res = ast_play_and_wait(chan, "digits/1M");
08647                if (!res)
08648                   res = ast_play_and_wait(chan, "vm-message");
08649                if (!res)
08650                   res = ast_play_and_wait(chan, "vm-INBOXs");
08651             } else {
08652                res = say_and_wait(chan, vms->newmessages, chan->language);
08653                if (!res)
08654                   res = ast_play_and_wait(chan, "vm-messages");
08655                if (!res)
08656                   res = ast_play_and_wait(chan, "vm-INBOX");
08657             }
08658          }
08659          if (vms->oldmessages && !res)
08660             res = ast_play_and_wait(chan, "vm-and");
08661       }
08662       if (vms->oldmessages) {
08663          if (!res) {
08664             if (vms->oldmessages == 1) {
08665                res = ast_play_and_wait(chan, "digits/1M");
08666                if (!res)
08667                   res = ast_play_and_wait(chan, "vm-message");
08668                if (!res)
08669                   res = ast_play_and_wait(chan, "vm-Olds");
08670             } else {
08671                res = say_and_wait(chan, vms->oldmessages, chan->language);
08672                if (!res)
08673                   res = ast_play_and_wait(chan, "vm-messages");
08674                if (!res)
08675                   res = ast_play_and_wait(chan, "vm-Old");
08676             }
08677          }
08678       }
08679    }
08680 return res;
08681 }

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

Definition at line 8729 of file app_voicemail_imapstorage.c.

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

08730 {
08731    /* Introduce messages they have */
08732    int res;
08733    res = ast_play_and_wait(chan, "vm-youhave");
08734    if (!res) {
08735       if (vms->newmessages) {
08736          res = say_and_wait(chan, vms->newmessages, chan->language);
08737          if (!res)
08738             res = ast_play_and_wait(chan, "vm-INBOX");
08739          if (vms->oldmessages && !res)
08740             res = ast_play_and_wait(chan, "vm-and");
08741          else if (!res) {
08742             if ((vms->newmessages == 1))
08743                res = ast_play_and_wait(chan, "vm-message");
08744             else
08745                res = ast_play_and_wait(chan, "vm-messages");
08746          }
08747             
08748       }
08749       if (!res && vms->oldmessages) {
08750          res = say_and_wait(chan, vms->oldmessages, chan->language);
08751          if (!res)
08752             res = ast_play_and_wait(chan, "vm-Old");
08753          if (!res) {
08754             if (vms->oldmessages == 1)
08755                res = ast_play_and_wait(chan, "vm-message");
08756             else
08757                res = ast_play_and_wait(chan, "vm-messages");
08758          }
08759       }
08760       if (!res) {
08761          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08762             res = ast_play_and_wait(chan, "vm-no");
08763             if (!res)
08764                res = ast_play_and_wait(chan, "vm-messages");
08765          }
08766       }
08767    }
08768    return res;
08769 }

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

Definition at line 8130 of file app_voicemail_imapstorage.c.

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

08131 {
08132    int res = 0;
08133 
08134    if (vms->newmessages) {
08135       res = ast_play_and_wait(chan, "vm-youhave");
08136       if (!res) 
08137          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08138       if (!res) {
08139          if ((vms->newmessages == 1)) {
08140             res = ast_play_and_wait(chan, "vm-INBOX");
08141             if (!res)
08142                res = ast_play_and_wait(chan, "vm-message");
08143          } else {
08144             res = ast_play_and_wait(chan, "vm-INBOXs");
08145             if (!res)
08146                res = ast_play_and_wait(chan, "vm-messages");
08147          }
08148       }
08149    } else if (vms->oldmessages){
08150       res = ast_play_and_wait(chan, "vm-youhave");
08151       if (!res)
08152          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08153       if ((vms->oldmessages == 1)){
08154          res = ast_play_and_wait(chan, "vm-Old");
08155          if (!res)
08156             res = ast_play_and_wait(chan, "vm-message");
08157       } else {
08158          res = ast_play_and_wait(chan, "vm-Olds");
08159          if (!res)
08160             res = ast_play_and_wait(chan, "vm-messages");
08161       }
08162    } else if (!vms->oldmessages && !vms->newmessages) 
08163       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08164    return res;
08165 }

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

Definition at line 8264 of file app_voicemail_imapstorage.c.

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

08265 {
08266    int res = 0;
08267 
08268    /* Introduce messages they have */
08269    if (!res) {
08270       if ((vms->newmessages) || (vms->oldmessages)) {
08271          res = ast_play_and_wait(chan, "vm-youhave");
08272       }
08273       /*
08274        * The word "shtei" refers to the number 2 in hebrew when performing a count
08275        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08276        * an element, this is one of them.
08277        */
08278       if (vms->newmessages) {
08279          if (!res) {
08280             if (vms->newmessages == 1) {
08281                res = ast_play_and_wait(chan, "vm-INBOX1");
08282             } else {
08283                if (vms->newmessages == 2) {
08284                   res = ast_play_and_wait(chan, "vm-shtei");
08285                } else {
08286                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08287                }
08288                res = ast_play_and_wait(chan, "vm-INBOX");
08289             }
08290          }
08291          if (vms->oldmessages && !res) {
08292             res = ast_play_and_wait(chan, "vm-and");
08293             if (vms->oldmessages == 1) {
08294                res = ast_play_and_wait(chan, "vm-Old1");
08295             } else {
08296                if (vms->oldmessages == 2) {
08297                   res = ast_play_and_wait(chan, "vm-shtei");
08298                } else {
08299                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08300                }
08301                res = ast_play_and_wait(chan, "vm-Old");
08302             }
08303          }
08304       }
08305       if (!res && vms->oldmessages && !vms->newmessages) {
08306          if (!res) {
08307             if (vms->oldmessages == 1) {
08308                res = ast_play_and_wait(chan, "vm-Old1");
08309             } else {
08310                if (vms->oldmessages == 2) {
08311                   res = ast_play_and_wait(chan, "vm-shtei");
08312                } else {
08313                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08314                }
08315                res = ast_play_and_wait(chan, "vm-Old");
08316             }
08317          }
08318       }
08319       if (!res) {
08320          if (!vms->oldmessages && !vms->newmessages) {
08321             if (!res) {
08322                res = ast_play_and_wait(chan, "vm-nomessages");
08323             }
08324          }
08325       }
08326    }
08327    return res;
08328 }

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

Definition at line 8388 of file app_voicemail_imapstorage.c.

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

08389 {
08390    /* Introduce messages they have */
08391    int res;
08392    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08393       res = ast_play_and_wait(chan, "vm-no") ||
08394          ast_play_and_wait(chan, "vm-message");
08395    else
08396       res = ast_play_and_wait(chan, "vm-youhave");
08397    if (!res && vms->newmessages) {
08398       res = (vms->newmessages == 1) ?
08399          ast_play_and_wait(chan, "digits/un") ||
08400          ast_play_and_wait(chan, "vm-nuovo") ||
08401          ast_play_and_wait(chan, "vm-message") :
08402          /* 2 or more new messages */
08403          say_and_wait(chan, vms->newmessages, chan->language) ||
08404          ast_play_and_wait(chan, "vm-nuovi") ||
08405          ast_play_and_wait(chan, "vm-messages");
08406       if (!res && vms->oldmessages)
08407          res = ast_play_and_wait(chan, "vm-and");
08408    }
08409    if (!res && vms->oldmessages) {
08410       res = (vms->oldmessages == 1) ?
08411          ast_play_and_wait(chan, "digits/un") ||
08412          ast_play_and_wait(chan, "vm-vecchio") ||
08413          ast_play_and_wait(chan, "vm-message") :
08414          /* 2 or more old messages */
08415          say_and_wait(chan, vms->oldmessages, chan->language) ||
08416          ast_play_and_wait(chan, "vm-vecchi") ||
08417          ast_play_and_wait(chan, "vm-messages");
08418    }
08419    return res;
08420 }

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

Definition at line 8224 of file app_voicemail_imapstorage.c.

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

08225 {
08226    int res;
08227    int lastnum = 0;
08228 
08229    res = ast_play_and_wait(chan, "vm-youhave");
08230 
08231    if (!res && vms->newmessages) {
08232       lastnum = vms->newmessages;
08233 
08234       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08235          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08236       }
08237 
08238       if (!res && vms->oldmessages) {
08239          res = ast_play_and_wait(chan, "vm-and");
08240       }
08241    }
08242 
08243    if (!res && vms->oldmessages) {
08244       lastnum = vms->oldmessages;
08245 
08246       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08247          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08248       }
08249    }
08250 
08251    if (!res) {
08252       if (lastnum == 0) {
08253          res = ast_play_and_wait(chan, "vm-no");
08254       }
08255       if (!res) {
08256          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08257       }
08258    }
08259 
08260    return res;
08261 }

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

Definition at line 8772 of file app_voicemail_imapstorage.c.

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

08773 {
08774    /* Introduce messages they have */
08775    int res;
08776    res = ast_play_and_wait(chan, "vm-youhave");
08777    if (!res) {
08778       if (vms->newmessages) {
08779          res = say_and_wait(chan, vms->newmessages, chan->language);
08780          if (!res) {
08781             if (vms->newmessages == 1)
08782                res = ast_play_and_wait(chan, "vm-INBOXs");
08783             else
08784                res = ast_play_and_wait(chan, "vm-INBOX");
08785          }
08786          if (vms->oldmessages && !res)
08787             res = ast_play_and_wait(chan, "vm-and");
08788          else if (!res) {
08789             if ((vms->newmessages == 1))
08790                res = ast_play_and_wait(chan, "vm-message");
08791             else
08792                res = ast_play_and_wait(chan, "vm-messages");
08793          }
08794             
08795       }
08796       if (!res && vms->oldmessages) {
08797          res = say_and_wait(chan, vms->oldmessages, chan->language);
08798          if (!res) {
08799             if (vms->oldmessages == 1)
08800                res = ast_play_and_wait(chan, "vm-Olds");
08801             else
08802                res = ast_play_and_wait(chan, "vm-Old");
08803          }
08804          if (!res) {
08805             if (vms->oldmessages == 1)
08806                res = ast_play_and_wait(chan, "vm-message");
08807             else
08808                res = ast_play_and_wait(chan, "vm-messages");
08809          }
08810       }
08811       if (!res) {
08812          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08813             res = ast_play_and_wait(chan, "vm-no");
08814             if (!res)
08815                res = ast_play_and_wait(chan, "vm-messages");
08816          }
08817       }
08818    }
08819    return res;
08820 }

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

Definition at line 8538 of file app_voicemail_imapstorage.c.

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

08539 {
08540    /* Introduce messages they have */
08541    int res;
08542 
08543    res = ast_play_and_wait(chan, "vm-youhave");
08544    if (res)
08545       return res;
08546 
08547    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08548       res = ast_play_and_wait(chan, "vm-no");
08549       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08550       return res;
08551    }
08552 
08553    if (vms->newmessages) {
08554       if ((vms->newmessages == 1)) {
08555          res = ast_play_and_wait(chan, "digits/1");
08556          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08557          res = res ? res : ast_play_and_wait(chan, "vm-message");
08558       } else {
08559          res = say_and_wait(chan, vms->newmessages, chan->language);
08560          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08561          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08562       }
08563       if (!res && vms->oldmessages)
08564          res = ast_play_and_wait(chan, "vm-and");
08565    }
08566    if (!res && vms->oldmessages) {
08567       if (vms->oldmessages == 1) {
08568          res = ast_play_and_wait(chan, "digits/1");
08569          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08570          res = res ? res : ast_play_and_wait(chan, "vm-message");
08571       } else {
08572          res = say_and_wait(chan, vms->oldmessages, chan->language);
08573          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08574          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08575       }
08576    }
08577 
08578    return res;
08579 }

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

Definition at line 8423 of file app_voicemail_imapstorage.c.

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

08424 {
08425    /* Introduce messages they have */
08426    int res;
08427    div_t num;
08428 
08429    if (!vms->oldmessages && !vms->newmessages) {
08430       res = ast_play_and_wait(chan, "vm-no");
08431       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08432       return res;
08433    } else {
08434       res = ast_play_and_wait(chan, "vm-youhave");
08435    }
08436 
08437    if (vms->newmessages) {
08438       num = div(vms->newmessages, 10);
08439       if (vms->newmessages == 1) {
08440          res = ast_play_and_wait(chan, "digits/1-a");
08441          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08442          res = res ? res : ast_play_and_wait(chan, "vm-message");
08443       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08444          if (num.rem == 2) {
08445             if (!num.quot) {
08446                res = ast_play_and_wait(chan, "digits/2-ie");
08447             } else {
08448                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08449                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08450             }
08451          } else {
08452             res = say_and_wait(chan, vms->newmessages, chan->language);
08453          }
08454          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08455          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08456       } else {
08457          res = say_and_wait(chan, vms->newmessages, chan->language);
08458          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08459          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08460       }
08461       if (!res && vms->oldmessages)
08462          res = ast_play_and_wait(chan, "vm-and");
08463    }
08464    if (!res && vms->oldmessages) {
08465       num = div(vms->oldmessages, 10);
08466       if (vms->oldmessages == 1) {
08467          res = ast_play_and_wait(chan, "digits/1-a");
08468          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08469          res = res ? res : ast_play_and_wait(chan, "vm-message");
08470       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08471          if (num.rem == 2) {
08472             if (!num.quot) {
08473                res = ast_play_and_wait(chan, "digits/2-ie");
08474             } else {
08475                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08476                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08477             }
08478          } else {
08479             res = say_and_wait(chan, vms->oldmessages, chan->language);
08480          }
08481          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08482          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08483       } else {
08484          res = say_and_wait(chan, vms->oldmessages, chan->language);
08485          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08486          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08487       }
08488    }
08489 
08490    return res;
08491 }

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

Definition at line 8823 of file app_voicemail_imapstorage.c.

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

08824 {
08825    /* Introduce messages they have */
08826    int res;
08827    res = ast_play_and_wait(chan, "vm-youhave");
08828    if (!res) {
08829       if (vms->newmessages) {
08830          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08831          if (!res) {
08832             if ((vms->newmessages == 1)) {
08833                res = ast_play_and_wait(chan, "vm-message");
08834                if (!res)
08835                   res = ast_play_and_wait(chan, "vm-INBOXs");
08836             } else {
08837                res = ast_play_and_wait(chan, "vm-messages");
08838                if (!res)
08839                   res = ast_play_and_wait(chan, "vm-INBOX");
08840             }
08841          }
08842          if (vms->oldmessages && !res)
08843             res = ast_play_and_wait(chan, "vm-and");
08844       }
08845       if (!res && vms->oldmessages) {
08846          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08847          if (!res) {
08848             if (vms->oldmessages == 1) {
08849                res = ast_play_and_wait(chan, "vm-message");
08850                if (!res)
08851                   res = ast_play_and_wait(chan, "vm-Olds");
08852             } else {
08853                res = ast_play_and_wait(chan, "vm-messages");
08854                if (!res)
08855                   res = ast_play_and_wait(chan, "vm-Old");
08856             }
08857          }
08858       }
08859       if (!res) {
08860          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08861             res = ast_play_and_wait(chan, "vm-no");
08862             if (!res)
08863                res = ast_play_and_wait(chan, "vm-messages");
08864          }
08865       }
08866    }
08867    return res;
08868 }

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

Definition at line 8684 of file app_voicemail_imapstorage.c.

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

08684                                                                           {
08685    /* Introduce messages they have */
08686    int res;
08687    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08688       res = ast_play_and_wait(chan, "vm-nomessages");
08689       return res;
08690    } else {
08691       res = ast_play_and_wait(chan, "vm-youhave");
08692    }
08693    if (vms->newmessages) {
08694       if (!res)
08695          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08696       if ((vms->newmessages == 1)) {
08697          if (!res)
08698             res = ast_play_and_wait(chan, "vm-message");
08699          if (!res)
08700             res = ast_play_and_wait(chan, "vm-INBOXs");
08701       } else {
08702          if (!res)
08703             res = ast_play_and_wait(chan, "vm-messages");
08704          if (!res)
08705             res = ast_play_and_wait(chan, "vm-INBOX");
08706       }
08707       if (vms->oldmessages && !res)
08708          res = ast_play_and_wait(chan, "vm-and");
08709    }
08710    if (vms->oldmessages) {
08711       if (!res)
08712          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08713       if (vms->oldmessages == 1) {
08714          if (!res)
08715             res = ast_play_and_wait(chan, "vm-message");
08716          if (!res)
08717             res = ast_play_and_wait(chan, "vm-Olds");
08718       } else {
08719          if (!res)
08720             res = ast_play_and_wait(chan, "vm-messages");
08721          if (!res)
08722             res = ast_play_and_wait(chan, "vm-Old");
08723       }
08724    }
08725    return res;
08726 }

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

Definition at line 8494 of file app_voicemail_imapstorage.c.

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

08495 {
08496    /* Introduce messages they have */
08497    int res;
08498 
08499    res = ast_play_and_wait(chan, "vm-youhave");
08500    if (res)
08501       return res;
08502 
08503    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08504       res = ast_play_and_wait(chan, "vm-no");
08505       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08506       return res;
08507    }
08508 
08509    if (vms->newmessages) {
08510       if ((vms->newmessages == 1)) {
08511          res = ast_play_and_wait(chan, "digits/ett");
08512          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08513          res = res ? res : ast_play_and_wait(chan, "vm-message");
08514       } else {
08515          res = say_and_wait(chan, vms->newmessages, chan->language);
08516          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08517          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08518       }
08519       if (!res && vms->oldmessages)
08520          res = ast_play_and_wait(chan, "vm-and");
08521    }
08522    if (!res && vms->oldmessages) {
08523       if (vms->oldmessages == 1) {
08524          res = ast_play_and_wait(chan, "digits/ett");
08525          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08526          res = res ? res : ast_play_and_wait(chan, "vm-message");
08527       } else {
08528          res = say_and_wait(chan, vms->oldmessages, chan->language);
08529          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08530          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08531       }
08532    }
08533 
08534    return res;
08535 }

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

Definition at line 8986 of file app_voicemail_imapstorage.c.

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

08987 {
08988    int res;
08989 
08990    /* Introduce messages they have */
08991    res = ast_play_and_wait(chan, "vm-youhave");
08992    if (!res) {
08993       if (vms->newmessages) {
08994          res = say_and_wait(chan, vms->newmessages, chan->language);
08995          if (!res)
08996             res = ast_play_and_wait(chan, "vm-INBOX");
08997          if (vms->oldmessages && !res)
08998             res = ast_play_and_wait(chan, "vm-and");
08999       }
09000       if (!res && vms->oldmessages) {
09001          res = say_and_wait(chan, vms->oldmessages, chan->language);
09002          if (!res)
09003             res = ast_play_and_wait(chan, "vm-Old");        
09004       }
09005       if (!res) {
09006          if (!vms->oldmessages && !vms->newmessages) {
09007             res = ast_play_and_wait(chan, "vm-no");
09008             if (!res)
09009                res = ast_play_and_wait(chan, "vm-message");
09010          }
09011       }
09012    }
09013    return res;
09014 }

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

Definition at line 8947 of file app_voicemail_imapstorage.c.

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

08948 {
08949    int res;
08950    /* Introduce messages they have */
08951    res = ast_play_and_wait(chan, "vm-you");
08952 
08953    if (!res && vms->newmessages) {
08954       res = ast_play_and_wait(chan, "vm-have");
08955       if (!res)
08956          res = say_and_wait(chan, vms->newmessages, chan->language);
08957       if (!res)
08958          res = ast_play_and_wait(chan, "vm-tong");
08959       if (!res)
08960          res = ast_play_and_wait(chan, "vm-INBOX");
08961       if (vms->oldmessages && !res)
08962          res = ast_play_and_wait(chan, "vm-and");
08963       else if (!res) 
08964          res = ast_play_and_wait(chan, "vm-messages");
08965    }
08966    if (!res && vms->oldmessages) {
08967       res = ast_play_and_wait(chan, "vm-have");
08968       if (!res)
08969          res = say_and_wait(chan, vms->oldmessages, chan->language);
08970       if (!res)
08971          res = ast_play_and_wait(chan, "vm-tong");
08972       if (!res)
08973          res = ast_play_and_wait(chan, "vm-Old");
08974       if (!res)
08975          res = ast_play_and_wait(chan, "vm-messages");
08976    }
08977    if (!res && !vms->oldmessages && !vms->newmessages) {
08978       res = ast_play_and_wait(chan, "vm-haveno");
08979       if (!res)
08980          res = ast_play_and_wait(chan, "vm-messages");
08981    }
08982    return res;
08983 }

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 3264 of file app_voicemail_imapstorage.c.

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03265 {
03266    switch (ast_lock_path(path)) {
03267    case AST_LOCK_TIMEOUT:
03268       return -1;
03269    default:
03270       return 0;
03271    }
03272 }

static FILE* vm_mkftemp ( char *  template  )  [static]

Definition at line 1666 of file app_voicemail_imapstorage.c.

References my_umask, and VOICEMAIL_FILE_MODE.

01667 {
01668    FILE *p = NULL;
01669    int pfd = mkstemp(template);
01670    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01671    if (pfd > -1) {
01672       p = fdopen(pfd, "w+");
01673       if (!p) {
01674          close(pfd);
01675          pfd = -1;
01676       }
01677    }
01678    return p;
01679 }

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

Definition at line 9189 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, adsi_logo(), ADSI_MSG_DISPLAY, ast_adsi_available(), ast_adsi_display(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, ast_fileexists(), ast_log(), AST_LOG_NOTICE, ast_play_and_wait(), ast_readstring(), ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, check_password(), ast_vm_user::context, ext_pass_cmd, maxgreet, 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.

09190 {
09191    int cmd = 0;
09192    int duration = 0;
09193    int tries = 0;
09194    char newpassword[80] = "";
09195    char newpassword2[80] = "";
09196    char prefile[PATH_MAX] = "";
09197    unsigned char buf[256];
09198    int bytes = 0;
09199 
09200    ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
09201    if (ast_adsi_available(chan)) {
09202       bytes += adsi_logo(buf + bytes);
09203       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09204       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09205       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09206       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09207       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09208    }
09209 
09210    /* If forcename is set, have the user record their name */
09211    if (ast_test_flag(vmu, VM_FORCENAME)) {
09212       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09213       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09214          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09215          if (cmd < 0 || cmd == 't' || cmd == '#')
09216             return cmd;
09217       }
09218    }
09219 
09220    /* If forcegreetings is set, have the user record their greetings */
09221    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09222       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09223       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09224          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09225          if (cmd < 0 || cmd == 't' || cmd == '#')
09226             return cmd;
09227       }
09228 
09229       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09230       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09231          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09232          if (cmd < 0 || cmd == 't' || cmd == '#')
09233             return cmd;
09234       }
09235    }
09236 
09237    /*
09238     * Change the password last since new users will be able to skip over any steps this one comes before
09239     * by hanging up and calling back to voicemail main since the password is used to verify new user status.
09240     */
09241    for (;;) {
09242       newpassword[1] = '\0';
09243       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09244       if (cmd == '#')
09245          newpassword[0] = '\0';
09246       if (cmd < 0 || cmd == 't' || cmd == '#')
09247          return cmd;
09248       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09249       if (cmd < 0 || cmd == 't' || cmd == '#')
09250          return cmd;
09251       cmd = check_password(vmu, newpassword); /* perform password validation */
09252       if (cmd != 0) {
09253          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09254          cmd = ast_play_and_wait(chan, vm_invalid_password);
09255       } else {
09256          newpassword2[1] = '\0';
09257          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09258          if (cmd == '#')
09259             newpassword2[0] = '\0';
09260          if (cmd < 0 || cmd == 't' || cmd == '#')
09261             return cmd;
09262          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09263          if (cmd < 0 || cmd == 't' || cmd == '#')
09264             return cmd;
09265          if (!strcmp(newpassword, newpassword2))
09266             break;
09267          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09268          cmd = ast_play_and_wait(chan, vm_mismatch);
09269       }
09270       if (++tries == 3)
09271          return -1;
09272       if (cmd != 0) {
09273          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09274       }
09275    }
09276    if (pwdchange & PWDCHANGE_INTERNAL)
09277       vm_change_password(vmu, newpassword);
09278    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09279       vm_change_password_shell(vmu, newpassword);
09280 
09281    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09282    cmd = ast_play_and_wait(chan, vm_passchanged);
09283 
09284    return cmd;
09285 }

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 9287 of file app_voicemail_imapstorage.c.

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

09288 {
09289    int cmd = 0;
09290    int retries = 0;
09291    int duration = 0;
09292    char newpassword[80] = "";
09293    char newpassword2[80] = "";
09294    char prefile[PATH_MAX] = "";
09295    unsigned char buf[256];
09296    int bytes = 0;
09297 
09298    ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
09299    if (ast_adsi_available(chan)) {
09300       bytes += adsi_logo(buf + bytes);
09301       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09302       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09303       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09304       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09305       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09306    }
09307    while ((cmd >= 0) && (cmd != 't')) {
09308       if (cmd)
09309          retries = 0;
09310       switch (cmd) {
09311       case '1': /* Record your unavailable message */
09312          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09313          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09314          break;
09315       case '2':  /* Record your busy message */
09316          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09317          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09318          break;
09319       case '3': /* Record greeting */
09320          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09321          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09322          break;
09323       case '4':  /* manage the temporary greeting */
09324          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09325          break;
09326       case '5': /* change password */
09327          if (vmu->password[0] == '-') {
09328             cmd = ast_play_and_wait(chan, "vm-no");
09329             break;
09330          }
09331          newpassword[1] = '\0';
09332          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09333          if (cmd == '#')
09334             newpassword[0] = '\0';
09335          else {
09336             if (cmd < 0)
09337                break;
09338             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09339                break;
09340             }
09341          }
09342          cmd = check_password(vmu, newpassword); /* perform password validation */
09343          if (cmd != 0) {
09344             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09345             cmd = ast_play_and_wait(chan, vm_invalid_password);
09346             if (!cmd) {
09347                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09348             }
09349             break;
09350          }
09351          newpassword2[1] = '\0';
09352          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09353          if (cmd == '#')
09354             newpassword2[0] = '\0';
09355          else {
09356             if (cmd < 0)
09357                break;
09358 
09359             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09360                break;
09361             }
09362          }
09363          if (strcmp(newpassword, newpassword2)) {
09364             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09365             cmd = ast_play_and_wait(chan, vm_mismatch);
09366             if (!cmd) {
09367                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09368             }
09369             break;
09370          }
09371 
09372          if (pwdchange & PWDCHANGE_INTERNAL) {
09373             vm_change_password(vmu, newpassword);
09374          }
09375          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) {
09376             vm_change_password_shell(vmu, newpassword);
09377          }
09378 
09379          ast_debug(1, "User %s set password to %s of length %d\n",
09380             vms->username, newpassword, (int) strlen(newpassword));
09381          cmd = ast_play_and_wait(chan, vm_passchanged);
09382          break;
09383       case '*': 
09384          cmd = 't';
09385          break;
09386       default: 
09387          cmd = 0;
09388          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09389          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09390          if (ast_fileexists(prefile, NULL, NULL)) {
09391             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09392          }
09393          DISPOSE(prefile, -1);
09394          if (!cmd) {
09395             cmd = ast_play_and_wait(chan, "vm-options");
09396          }
09397          if (!cmd) {
09398             cmd = ast_waitfordigit(chan, 6000);
09399          }
09400          if (!cmd) {
09401             retries++;
09402          }
09403          if (retries > 3) {
09404             cmd = 't';
09405          }
09406          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09407       }
09408    }
09409    if (cmd == 't')
09410       cmd = 0;
09411    return cmd;
09412 }

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

Definition at line 8093 of file app_voicemail_imapstorage.c.

References ast_play_and_wait(), ast_channel::language, vm_play_folder_name_gr(), vm_play_folder_name_pl(), and vm_play_folder_name_ua().

08094 {
08095    int cmd;
08096 
08097    if (  !strncasecmp(chan->language, "it", 2) ||
08098         !strncasecmp(chan->language, "es", 2) ||
08099         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08100       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08101       return cmd ? cmd : ast_play_and_wait(chan, box);
08102    } else if (!strncasecmp(chan->language, "gr", 2)) {
08103       return vm_play_folder_name_gr(chan, box);
08104    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08105       return ast_play_and_wait(chan, box);
08106    } else if (!strncasecmp(chan->language, "pl", 2)) {
08107       return vm_play_folder_name_pl(chan, box);
08108    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08109       return vm_play_folder_name_ua(chan, box);
08110    } else if (!strncasecmp(chan->language, "vi", 2)) {
08111       return ast_play_and_wait(chan, box);
08112    } else {  /* Default English */
08113       cmd = ast_play_and_wait(chan, box);
08114       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08115    }
08116 }

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

Definition at line 8046 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

08047 {
08048    int cmd;
08049    char *buf;
08050 
08051    buf = alloca(strlen(box) + 2);
08052    strcpy(buf, box);
08053    strcat(buf, "s");
08054 
08055    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08056       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08057       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08058    } else {
08059       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08060       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08061    }
08062 }

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

Definition at line 8064 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

08065 {
08066    int cmd;
08067 
08068    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08069       if (!strcasecmp(box, "vm-INBOX"))
08070          cmd = ast_play_and_wait(chan, "vm-new-e");
08071       else
08072          cmd = ast_play_and_wait(chan, "vm-old-e");
08073       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08074    } else {
08075       cmd = ast_play_and_wait(chan, "vm-messages");
08076       return cmd ? cmd : ast_play_and_wait(chan, box);
08077    }
08078 }

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

Definition at line 8080 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

08081 {
08082    int cmd;
08083 
08084    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08085       cmd = ast_play_and_wait(chan, "vm-messages");
08086       return cmd ? cmd : ast_play_and_wait(chan, box);
08087    } else {
08088       cmd = ast_play_and_wait(chan, box);
08089       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08090    }
08091 }

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 9430 of file app_voicemail_imapstorage.c.

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

09431 {
09432    int cmd = 0;
09433    int retries = 0;
09434    int duration = 0;
09435    char prefile[PATH_MAX] = "";
09436    unsigned char buf[256];
09437    int bytes = 0;
09438 
09439    if (ast_adsi_available(chan)) {
09440       bytes += adsi_logo(buf + bytes);
09441       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09442       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09443       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09444       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09445       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09446    }
09447 
09448    ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
09449    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09450    while ((cmd >= 0) && (cmd != 't')) {
09451       if (cmd)
09452          retries = 0;
09453       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09454       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09455          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09456          cmd = 't';  
09457       } else {
09458          switch (cmd) {
09459          case '1':
09460             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09461             break;
09462          case '2':
09463             DELETE(prefile, -1, prefile, vmu);
09464             ast_play_and_wait(chan, "vm-tempremoved");
09465             cmd = 't';  
09466             break;
09467          case '*': 
09468             cmd = 't';
09469             break;
09470          default:
09471             cmd = ast_play_and_wait(chan,
09472                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09473                   "vm-tempgreeting2" : "vm-tempgreeting");
09474             if (!cmd) {
09475                cmd = ast_waitfordigit(chan, 6000);
09476             }
09477             if (!cmd) {
09478                retries++;
09479             }
09480             if (retries > 3) {
09481                cmd = 't';
09482             }
09483             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09484          }
09485       }
09486       DISPOSE(prefile, -1);
09487    }
09488    if (cmd == 't')
09489       cmd = 0;
09490    return cmd;
09491 }

static int vm_users_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
) [static]

Definition at line 11393 of file app_voicemail_imapstorage.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_vm_user::list, user, and vm_users_data_provider_get_helper().

11395 {
11396    struct ast_vm_user *user;
11397 
11398    AST_LIST_LOCK(&users);
11399    AST_LIST_TRAVERSE(&users, user, list) {
11400       vm_users_data_provider_get_helper(search, data_root, user);
11401    }
11402    AST_LIST_UNLOCK(&users);
11403 
11404    return 0;
11405 }

static int vm_users_data_provider_get_helper ( const struct ast_data_search search,
struct ast_data data_root,
struct ast_vm_user user 
) [static]

Definition at line 11346 of file app_voicemail_imapstorage.c.

References ast_data_add_int(), ast_data_add_node(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, inboxcount2(), vm_zone::list, vm_zone::name, and user.

11348 {
11349    struct ast_data *data_user, *data_zone;
11350    struct ast_data *data_state;
11351    struct vm_zone *zone = NULL;
11352    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11353    char ext_context[256] = "";
11354 
11355    data_user = ast_data_add_node(data_root, "user");
11356    if (!data_user) {
11357       return -1;
11358    }
11359 
11360    ast_data_add_structure(ast_vm_user, data_user, user);
11361 
11362    AST_LIST_LOCK(&zones);
11363    AST_LIST_TRAVERSE(&zones, zone, list) {
11364       if (!strcmp(zone->name, user->zonetag)) {
11365          break;
11366       }
11367    }
11368    AST_LIST_UNLOCK(&zones);
11369 
11370    /* state */
11371    data_state = ast_data_add_node(data_user, "state");
11372    if (!data_state) {
11373       return -1;
11374    }
11375    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11376    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11377    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11378    ast_data_add_int(data_state, "newmsg", newmsg);
11379    ast_data_add_int(data_state, "oldmsg", oldmsg);
11380 
11381    if (zone) {
11382       data_zone = ast_data_add_node(data_user, "zone");
11383       ast_data_add_structure(vm_zone, data_zone, zone);
11384    }
11385 
11386    if (!ast_data_search_match(search, data_user)) {
11387       ast_data_remove_node(data_root, data_user);
11388    }
11389 
11390    return 0;
11391 }

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

Definition at line 11032 of file app_voicemail_imapstorage.c.

References ast_copy_string(), ast_goto_if_exists(), AST_MAX_EXTENSION, ast_play_and_wait(), ast_strdupa, ast_strlen_zero(), ast_channel::context, ast_vm_user::context, pbx_builtin_setvar_helper(), strsep(), and vm_authenticate().

11033 {
11034    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11035    struct ast_vm_user vmus;
11036    char *options = NULL;
11037    int silent = 0, skipuser = 0;
11038    int res = -1;
11039    
11040    if (data) {
11041       s = ast_strdupa(data);
11042       user = strsep(&s, ",");
11043       options = strsep(&s, ",");
11044       if (user) {
11045          s = user;
11046          user = strsep(&s, "@");
11047          context = strsep(&s, "");
11048          if (!ast_strlen_zero(user))
11049             skipuser++;
11050          ast_copy_string(mailbox, user, sizeof(mailbox));
11051       }
11052    }
11053 
11054    if (options) {
11055       silent = (strchr(options, 's')) != NULL;
11056    }
11057 
11058    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11059       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11060       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11061       ast_play_and_wait(chan, "auth-thankyou");
11062       res = 0;
11063    } else if (mailbox[0] == '*') {
11064       /* user entered '*' */
11065       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11066          res = 0; /* prevent hangup */
11067       }
11068    }
11069 
11070    return res;
11071 }

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

Definition at line 12550 of file app_voicemail_imapstorage.c.

References ast_debug, AST_DIGIT_ANY, ast_log(), ast_say_character_str(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_channel::language, LOG_WARNING, and sayname().

12551 {
12552    char *context;
12553    char *args_copy;
12554    int res;
12555 
12556    if (ast_strlen_zero(data)) {
12557       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context");
12558       return -1;
12559    }
12560 
12561    args_copy = ast_strdupa(data);
12562    if ((context = strchr(args_copy, '@'))) {
12563       *context++ = '\0';
12564    } else {
12565       context = "default";
12566    }
12567 
12568    if ((res = sayname(chan, args_copy, context) < 0)) {
12569       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12570       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12571       if (!res) {
12572          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12573       }
12574    }
12575 
12576    return res;
12577 }

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

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

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

Definition at line 4419 of file app_voicemail_imapstorage.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_localtime(), ast_strlen_zero(), ast_tvnow(), vm_zone::name, vm_zone::timezone, and ast_vm_user::zonetag.

04420 {
04421    const struct vm_zone *z = NULL;
04422    struct timeval t = ast_tvnow();
04423 
04424    /* Does this user have a timezone specified? */
04425    if (!ast_strlen_zero(vmu->zonetag)) {
04426       /* Find the zone in the list */
04427       AST_LIST_LOCK(&zones);
04428       AST_LIST_TRAVERSE(&zones, z, list) {
04429          if (!strcmp(z->name, vmu->zonetag))
04430             break;
04431       }
04432       AST_LIST_UNLOCK(&zones);
04433    }
04434    ast_localtime(&t, tm, z ? z->timezone : NULL);
04435    return tm;
04436 }

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

Definition at line 7454 of file app_voicemail_imapstorage.c.

References ast_control_streamfile(), ast_test_suite_event_notify, listen_control_forward_key, listen_control_pause_key, listen_control_restart_key, listen_control_reverse_key, listen_control_stop_key, and skipms.

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

Definition at line 7446 of file app_voicemail_imapstorage.c.

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

07447 {
07448    int res;
07449    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07450       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07451    return res;
07452 }

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

Definition at line 12524 of file app_voicemail_imapstorage.c.

References ast_category_append(), ast_category_new(), ast_config_new(), ast_config_text_file_save(), ast_log(), ast_variable_append(), ast_variable_new(), LOG_ERROR, and var.

12524                                                                               {
12525    struct ast_config *conf;
12526    struct ast_category *cat;
12527    struct ast_variable *var;
12528 
12529    if (!(conf=ast_config_new())) {
12530       ast_log(LOG_ERROR, "Error creating new config structure\n");
12531       return -1;
12532    }
12533    if (!(cat=ast_category_new("general","",1))) {
12534       ast_log(LOG_ERROR, "Error creating new category structure\n");
12535       return -1;
12536    }
12537    if (!(var=ast_variable_new("password",password,""))) {
12538       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12539       return -1;
12540    }
12541    ast_category_append(conf,cat);
12542    ast_variable_append(cat,var);
12543    if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12544       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12545       return -1;
12546    }
12547    return 0;
12548 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", } [static]

Definition at line 13629 of file app_voicemail_imapstorage.c.

char* addesc = "Comedian Mail" [static]

Definition at line 777 of file app_voicemail_imapstorage.c.

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

Definition at line 904 of file app_voicemail_imapstorage.c.

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

Definition at line 905 of file app_voicemail_imapstorage.c.

int adsiver = 1 [static]

Definition at line 906 of file app_voicemail_imapstorage.c.

char* app = "VoiceMail" [static]

Definition at line 780 of file app_voicemail_imapstorage.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 783 of file app_voicemail_imapstorage.c.

char* app3 = "MailboxExists" [static]

Definition at line 785 of file app_voicemail_imapstorage.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 786 of file app_voicemail_imapstorage.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 13629 of file app_voicemail_imapstorage.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 890 of file app_voicemail_imapstorage.c.

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

Definition at line 902 of file app_voicemail_imapstorage.c.

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

Definition at line 893 of file app_voicemail_imapstorage.c.

struct ast_cli_entry cli_voicemail[] [static]

Initial value:

 {
   { .handler =  handle_voicemail_show_users , .summary =  "List defined voicemail boxes" ,__VA_ARGS__ },
   { .handler =  handle_voicemail_show_zones , .summary =  "List zone message formats" ,__VA_ARGS__ },
   { .handler =  handle_voicemail_reload , .summary =  "Reload voicemail configuration" ,__VA_ARGS__ },
}

Definition at line 11269 of file app_voicemail_imapstorage.c.

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 889 of file app_voicemail_imapstorage.c.

char* emailbody = NULL [static]

Definition at line 896 of file app_voicemail_imapstorage.c.

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

Definition at line 907 of file app_voicemail_imapstorage.c.

char* emailsubject = NULL [static]

Definition at line 897 of file app_voicemail_imapstorage.c.

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 891 of file app_voicemail_imapstorage.c.

char ext_pass_check_cmd[128] [static]

Definition at line 757 of file app_voicemail_imapstorage.c.

char ext_pass_cmd[128] [static]

Definition at line 756 of file app_voicemail_imapstorage.c.

char externnotify[160] [static]

Definition at line 800 of file app_voicemail_imapstorage.c.

char fromstring[100] [static]

Definition at line 900 of file app_voicemail_imapstorage.c.

struct ast_flags globalflags = {0} [static]

Definition at line 885 of file app_voicemail_imapstorage.c.

struct ao2_container* inprocess_container

Definition at line 929 of file app_voicemail_imapstorage.c.

char listen_control_forward_key[12] [static]

Definition at line 858 of file app_voicemail_imapstorage.c.

char listen_control_pause_key[12] [static]

Definition at line 860 of file app_voicemail_imapstorage.c.

char listen_control_restart_key[12] [static]

Definition at line 861 of file app_voicemail_imapstorage.c.

char listen_control_reverse_key[12] [static]

Definition at line 859 of file app_voicemail_imapstorage.c.

char listen_control_stop_key[12] [static]

Definition at line 862 of file app_voicemail_imapstorage.c.

char locale[20] [static]

Definition at line 793 of file app_voicemail_imapstorage.c.

struct ast_custom_function mailbox_exists_acf [static]

Initial value:

 {
   .name = "MAILBOX_EXISTS",
   .read = acf_mailbox_exists,
}

Definition at line 11027 of file app_voicemail_imapstorage.c.

const char* const mailbox_folders[] [static]

Definition at line 1702 of file app_voicemail_imapstorage.c.

char mailcmd[160] [static]

Definition at line 799 of file app_voicemail_imapstorage.c.

int maxdeletedmsg [static]

Definition at line 796 of file app_voicemail_imapstorage.c.

int maxgreet [static]

Definition at line 806 of file app_voicemail_imapstorage.c.

int maxlogins [static]

Definition at line 808 of file app_voicemail_imapstorage.c.

int maxmsg [static]

Definition at line 795 of file app_voicemail_imapstorage.c.

int maxsilence [static]

Definition at line 794 of file app_voicemail_imapstorage.c.

int minpassword [static]

Definition at line 809 of file app_voicemail_imapstorage.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 827 of file app_voicemail_imapstorage.c.

struct ast_taskprocessor* mwi_subscription_tps [static]

Definition at line 853 of file app_voicemail_imapstorage.c.

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 829 of file app_voicemail_imapstorage.c.

int my_umask [static]

Definition at line 759 of file app_voicemail_imapstorage.c.

char* pagerbody = NULL [static]

Definition at line 898 of file app_voicemail_imapstorage.c.

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

Definition at line 908 of file app_voicemail_imapstorage.c.

char pagerfromstring[100] [static]

Definition at line 901 of file app_voicemail_imapstorage.c.

char* pagersubject = NULL [static]

Definition at line 899 of file app_voicemail_imapstorage.c.

int passwordlocation [static]

Definition at line 810 of file app_voicemail_imapstorage.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 822 of file app_voicemail_imapstorage.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 817 of file app_voicemail_imapstorage.c.

ast_mutex_t poll_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 821 of file app_voicemail_imapstorage.c.

unsigned int poll_mailboxes [static]

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

Definition at line 814 of file app_voicemail_imapstorage.c.

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 823 of file app_voicemail_imapstorage.c.

unsigned char poll_thread_run [static]

Definition at line 824 of file app_voicemail_imapstorage.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 763 of file app_voicemail_imapstorage.c.

int saydurationminfo [static]

Definition at line 887 of file app_voicemail_imapstorage.c.

char* sayname_app = "VMSayName" [static]

Definition at line 788 of file app_voicemail_imapstorage.c.

char serveremail[80] [static]

Definition at line 798 of file app_voicemail_imapstorage.c.

int silencethreshold = 128 [static]

Definition at line 797 of file app_voicemail_imapstorage.c.

int skipms [static]

Definition at line 807 of file app_voicemail_imapstorage.c.

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 801 of file app_voicemail_imapstorage.c.

char userscontext[AST_MAX_EXTENSION] = "default" [static]

Definition at line 775 of file app_voicemail_imapstorage.c.

struct ast_app_option vm_app_options[128] = { [ 's' ] = { .flag = OPT_SILENT }, [ 'b' ] = { .flag = OPT_BUSY_GREETING }, [ 'u' ] = { .flag = OPT_UNAVAIL_GREETING }, [ 'g' ] = { .flag = OPT_RECORDGAIN , .arg_index = OPT_ARG_RECORDGAIN + 1 }, [ 'd' ] = { .flag = OPT_DTMFEXIT , .arg_index = OPT_ARG_DTMFEXIT + 1 }, [ 'p' ] = { .flag = OPT_PREPEND_MAILBOX }, [ 'a' ] = { .flag = OPT_AUTOPLAY , .arg_index = OPT_ARG_PLAYFOLDER + 1 }, [ 'U' ] = { .flag = OPT_MESSAGE_Urgent }, [ 'P' ] = { .flag = OPT_MESSAGE_PRIORITY }} [static]

Definition at line 540 of file app_voicemail_imapstorage.c.

struct ast_data_entry vm_data_providers[] [static]

Initial value:

 {

}

Definition at line 11412 of file app_voicemail_imapstorage.c.

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

Definition at line 870 of file app_voicemail_imapstorage.c.

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

Definition at line 869 of file app_voicemail_imapstorage.c.

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

Definition at line 866 of file app_voicemail_imapstorage.c.

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

Definition at line 867 of file app_voicemail_imapstorage.c.

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

Definition at line 865 of file app_voicemail_imapstorage.c.

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

Definition at line 871 of file app_voicemail_imapstorage.c.

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

Definition at line 883 of file app_voicemail_imapstorage.c.

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

Definition at line 868 of file app_voicemail_imapstorage.c.

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 754 of file app_voicemail_imapstorage.c.

struct ast_data_handler vm_users_data_provider [static]

Initial value:

Definition at line 11407 of file app_voicemail_imapstorage.c.

char vmfmts[80] [static]

Definition at line 802 of file app_voicemail_imapstorage.c.

int vmmaxsecs [static]

Definition at line 805 of file app_voicemail_imapstorage.c.

int vmminsecs [static]

Definition at line 804 of file app_voicemail_imapstorage.c.

double volgain [static]

Definition at line 803 of file app_voicemail_imapstorage.c.

char zonetag[80] [static]

Definition at line 792 of file app_voicemail_imapstorage.c.


Generated on Sat Mar 10 01:54:42 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7