Mon Oct 8 12:39:09 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 = "ac1f6a56484a8820659555499174e588" , .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 11341 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 11369 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 5385 of file app_voicemail_imapstorage.c.

References ast_strlen_zero(), and VM_SPOOL_DIR.

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

static void __reg_module ( void   )  [static]

Definition at line 13688 of file app_voicemail_imapstorage.c.

static void __unreg_module ( void   )  [static]

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

11044 {
11045    struct ast_vm_user svm;
11046    AST_DECLARE_APP_ARGS(arg,
11047       AST_APP_ARG(mbox);
11048       AST_APP_ARG(context);
11049    );
11050 
11051    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
11052 
11053    if (ast_strlen_zero(arg.mbox)) {
11054       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11055       return -1;
11056    }
11057 
11058    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
11059    return 0;
11060 }

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

Definition at line 11879 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.

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

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

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

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

Definition at line 6405 of file app_voicemail_imapstorage.c.

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

06406 {
06407    int x;
06408    if (!ast_adsi_available(chan))
06409       return;
06410    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06411    if (x < 0)
06412       return;
06413    if (!x) {
06414       if (adsi_load_vmail(chan, useadsi)) {
06415          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06416          return;
06417       }
06418    } else
06419       *useadsi = 1;
06420 }

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

Definition at line 6600 of file app_voicemail_imapstorage.c.

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

06601 {
06602    int bytes = 0;
06603    unsigned char buf[256];
06604    unsigned char keys[8];
06605 
06606    int x;
06607 
06608    if (!ast_adsi_available(chan))
06609       return;
06610 
06611    /* New meaning for keys */
06612    for (x = 0; x < 5; x++)
06613       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06614 
06615    keys[6] = 0x0;
06616    keys[7] = 0x0;
06617 
06618    if (!vms->curmsg) {
06619       /* No prev key, provide "Folder" instead */
06620       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06621    }
06622    if (vms->curmsg >= vms->lastmsg) {
06623       /* If last message ... */
06624       if (vms->curmsg) {
06625          /* but not only message, provide "Folder" instead */
06626          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06627       } else {
06628          /* Otherwise if only message, leave blank */
06629          keys[3] = 1;
06630       }
06631    }
06632 
06633    /* If deleted, show "undeleted" */
06634 #ifdef IMAP_STORAGE
06635    ast_mutex_lock(&vms->lock);
06636 #endif
06637    if (vms->deleted[vms->curmsg]) {
06638       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06639    }
06640 #ifdef IMAP_STORAGE
06641    ast_mutex_unlock(&vms->lock);
06642 #endif
06643 
06644    /* Except "Exit" */
06645    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06646    bytes += ast_adsi_set_keys(buf + bytes, keys);
06647    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06648 
06649    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06650 }

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

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

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

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06756 {
06757    unsigned char buf[256];
06758    int bytes = 0;
06759 
06760    if (!ast_adsi_available(chan))
06761       return;
06762    bytes += adsi_logo(buf + bytes);
06763    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06764    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06765    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06766    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06767 
06768    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06769 }

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

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

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

static void adsi_login ( struct ast_channel chan  )  [static]

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

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

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

Definition at line 6268 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display().

06269 {
06270    int bytes = 0;
06271    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06272    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06273    return bytes;
06274 }

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

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

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

static void adsi_password ( struct ast_channel chan  )  [static]

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

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

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

Definition at line 6652 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(), buf2, vm_state::lastmsg, vm_state::newmessages, and vm_state::oldmessages.

06653 {
06654    unsigned char buf[256] = "";
06655    char buf1[256] = "", buf2[256] = "";
06656    int bytes = 0;
06657    unsigned char keys[8];
06658    int x;
06659 
06660    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06661    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06662    if (!ast_adsi_available(chan))
06663       return;
06664    if (vms->newmessages) {
06665       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06666       if (vms->oldmessages) {
06667          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06668          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06669       } else {
06670          snprintf(buf2, sizeof(buf2), "%s.", newm);
06671       }
06672    } else if (vms->oldmessages) {
06673       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06674       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06675    } else {
06676       strcpy(buf1, "You have no messages.");
06677       buf2[0] = ' ';
06678       buf2[1] = '\0';
06679    }
06680    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06681    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06682    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06683 
06684    for (x = 0; x < 6; x++)
06685       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06686    keys[6] = 0;
06687    keys[7] = 0;
06688 
06689    /* Don't let them listen if there are none */
06690    if (vms->lastmsg < 0)
06691       keys[0] = 1;
06692    bytes += ast_adsi_set_keys(buf + bytes, keys);
06693 
06694    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06695 
06696    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06697 }

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

Definition at line 6699 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(), buf2, vm_state::curbox, and vm_state::lastmsg.

06700 {
06701    unsigned char buf[256] = "";
06702    char buf1[256] = "", buf2[256] = "";
06703    int bytes = 0;
06704    unsigned char keys[8];
06705    int x;
06706 
06707    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06708 
06709    if (!ast_adsi_available(chan))
06710       return;
06711 
06712    /* Original command keys */
06713    for (x = 0; x < 6; x++)
06714       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06715 
06716    keys[6] = 0;
06717    keys[7] = 0;
06718 
06719    if ((vms->lastmsg + 1) < 1)
06720       keys[0] = 0;
06721 
06722    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06723       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06724 
06725    if (vms->lastmsg + 1)
06726       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06727    else
06728       strcpy(buf2, "no messages.");
06729    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06730    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06731    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06732    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06733    bytes += ast_adsi_set_keys(buf + bytes, keys);
06734 
06735    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06736 
06737    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06738    
06739 }

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

13251 {
13252    int res = 0;
13253    char filename[PATH_MAX];
13254    struct ast_config *msg_cfg = NULL;
13255    const char *origtime, *context;
13256    char *name, *num;
13257    int retries = 0;
13258    char *cid;
13259    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
13260 
13261    vms->starting = 0; 
13262 
13263    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13264 
13265    /* Retrieve info from VM attribute file */
13266    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
13267    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
13268    msg_cfg = ast_config_load(filename, config_flags);
13269    DISPOSE(vms->curdir, vms->curmsg);
13270    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
13271       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
13272       return 0;
13273    }
13274 
13275    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
13276       ast_config_destroy(msg_cfg);
13277       return 0;
13278    }
13279 
13280    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
13281 
13282    context = ast_variable_retrieve(msg_cfg, "message", "context");
13283    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
13284       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
13285    switch (option) {
13286    case 3: /* Play message envelope */
13287       if (!res)
13288          res = play_message_datetime(chan, vmu, origtime, filename);
13289       if (!res)
13290          res = play_message_callerid(chan, vms, cid, context, 0);
13291 
13292       res = 't';
13293       break;
13294 
13295    case 2:  /* Call back */
13296 
13297       if (ast_strlen_zero(cid))
13298          break;
13299 
13300       ast_callerid_parse(cid, &name, &num);
13301       while ((res > -1) && (res != 't')) {
13302          switch (res) {
13303          case '1':
13304             if (num) {
13305                /* Dial the CID number */
13306                res = dialout(chan, vmu, num, vmu->callback);
13307                if (res) {
13308                   ast_config_destroy(msg_cfg);
13309                   return 9;
13310                }
13311             } else {
13312                res = '2';
13313             }
13314             break;
13315 
13316          case '2':
13317             /* Want to enter a different number, can only do this if there's a dialout context for this user */
13318             if (!ast_strlen_zero(vmu->dialout)) {
13319                res = dialout(chan, vmu, NULL, vmu->dialout);
13320                if (res) {
13321                   ast_config_destroy(msg_cfg);
13322                   return 9;
13323                }
13324             } else {
13325                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
13326                res = ast_play_and_wait(chan, "vm-sorry");
13327             }
13328             ast_config_destroy(msg_cfg);
13329             return res;
13330          case '*':
13331             res = 't';
13332             break;
13333          case '3':
13334          case '4':
13335          case '5':
13336          case '6':
13337          case '7':
13338          case '8':
13339          case '9':
13340          case '0':
13341 
13342             res = ast_play_and_wait(chan, "vm-sorry");
13343             retries++;
13344             break;
13345          default:
13346             if (num) {
13347                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
13348                res = ast_play_and_wait(chan, "vm-num-i-have");
13349                if (!res)
13350                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
13351                if (!res)
13352                   res = ast_play_and_wait(chan, "vm-tocallnum");
13353                /* Only prompt for a caller-specified number if there is a dialout context specified */
13354                if (!ast_strlen_zero(vmu->dialout)) {
13355                   if (!res)
13356                      res = ast_play_and_wait(chan, "vm-calldiffnum");
13357                }
13358             } else {
13359                res = ast_play_and_wait(chan, "vm-nonumber");
13360                if (!ast_strlen_zero(vmu->dialout)) {
13361                   if (!res)
13362                      res = ast_play_and_wait(chan, "vm-toenternumber");
13363                }
13364             }
13365             if (!res) {
13366                res = ast_play_and_wait(chan, "vm-star-cancel");
13367             }
13368             if (!res) {
13369                res = ast_waitfordigit(chan, 6000);
13370             }
13371             if (!res) {
13372                retries++;
13373                if (retries > 3) {
13374                   res = 't';
13375                }
13376             }
13377             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
13378             break; 
13379             
13380          }
13381          if (res == 't')
13382             res = 0;
13383          else if (res == '*')
13384             res = -1;
13385       }
13386       break;
13387       
13388    case 1:  /* Reply */
13389       /* Send reply directly to sender */
13390       if (ast_strlen_zero(cid))
13391          break;
13392 
13393       ast_callerid_parse(cid, &name, &num);
13394       if (!num) {
13395          ast_verb(3, "No CID number available, no reply sent\n");
13396          if (!res)
13397             res = ast_play_and_wait(chan, "vm-nonumber");
13398          ast_config_destroy(msg_cfg);
13399          return res;
13400       } else {
13401          struct ast_vm_user vmu2;
13402          if (find_user(&vmu2, vmu->context, num)) {
13403             struct leave_vm_options leave_options;
13404             char mailbox[AST_MAX_EXTENSION * 2 + 2];
13405             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
13406 
13407             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
13408             
13409             memset(&leave_options, 0, sizeof(leave_options));
13410             leave_options.record_gain = record_gain;
13411             res = leave_voicemail(chan, mailbox, &leave_options);
13412             if (!res)
13413                res = 't';
13414             ast_config_destroy(msg_cfg);
13415             return res;
13416          } else {
13417             /* Sender has no mailbox, can't reply */
13418             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
13419             ast_play_and_wait(chan, "vm-nobox");
13420             res = 't';
13421             ast_config_destroy(msg_cfg);
13422             return res;
13423          }
13424       } 
13425       res = 0;
13426 
13427       break;
13428    }
13429 
13430 #ifndef IMAP_STORAGE
13431    ast_config_destroy(msg_cfg);
13432 
13433    if (!res) {
13434       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
13435       vms->heard[msg] = 1;
13436       res = wait_file(chan, vms, vms->fn);
13437    }
13438 #endif
13439    return res;
13440 }

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

Definition at line 10770 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.

10771 {
10772    /* Assumes lock is already held */
10773    char *tmp;
10774    char *stringp;
10775    char *s;
10776    struct ast_vm_user *vmu;
10777    char *mailbox_full;
10778    int new = 0, old = 0, urgent = 0;
10779    char secretfn[PATH_MAX] = "";
10780 
10781    tmp = ast_strdupa(data);
10782 
10783    if (!(vmu = find_or_create(context, box)))
10784       return -1;
10785 
10786    populate_defaults(vmu);
10787 
10788    stringp = tmp;
10789    if ((s = strsep(&stringp, ","))) {
10790       if (!ast_strlen_zero(s) && s[0] == '*') {
10791          ast_log(LOG_WARNING, "Invalid password detected for mailbox %s.  The password"
10792             "\n\tmust be reset in voicemail.conf.\n", box);
10793       }
10794       /* assign password regardless of validity to prevent NULL password from being assigned */
10795       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10796    }
10797    if (stringp && (s = strsep(&stringp, ","))) {
10798       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10799    }
10800    if (stringp && (s = strsep(&stringp, ","))) {
10801       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10802    }
10803    if (stringp && (s = strsep(&stringp, ","))) {
10804       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10805    }
10806    if (stringp && (s = strsep(&stringp, ","))) {
10807       apply_options(vmu, s);
10808    }
10809 
10810    switch (vmu->passwordlocation) {
10811    case OPT_PWLOC_SPOOLDIR:
10812       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10813       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10814    }
10815 
10816    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10817    strcpy(mailbox_full, box);
10818    strcat(mailbox_full, "@");
10819    strcat(mailbox_full, context);
10820 
10821    inboxcount2(mailbox_full, &urgent, &new, &old);
10822    queue_mwi_event(mailbox_full, urgent, new, old);
10823 
10824    return 0;
10825 }

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

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

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

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

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

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

Definition at line 10827 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.

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

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

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

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

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

04448 {
04449    for (; *str; str++) {
04450       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04451          return 1;
04452       }
04453    }
04454    return 0;
04455 }

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

07966 {
07967    int x = 0;
07968    int last_msg_idx = 0;
07969 
07970 #ifndef IMAP_STORAGE
07971    int res = 0, nummsg;
07972    char fn2[PATH_MAX];
07973 #endif
07974 
07975    if (vms->lastmsg <= -1) {
07976       goto done;
07977    }
07978 
07979    vms->curmsg = -1;
07980 #ifndef IMAP_STORAGE
07981    /* Get the deleted messages fixed */
07982    if (vm_lock_path(vms->curdir)) {
07983       return ERROR_LOCK_PATH;
07984    }
07985 
07986    /* update count as message may have arrived while we've got mailbox open */
07987    last_msg_idx = last_message_index(vmu, vms->curdir);
07988    if (last_msg_idx != vms->lastmsg) {
07989       ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
07990    }
07991 
07992    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07993    for (x = 0; x < last_msg_idx + 1; x++) {
07994       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07995          /* Save this message.  It's not in INBOX or hasn't been heard */
07996          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07997          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07998             break;
07999          }
08000          vms->curmsg++;
08001          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
08002          if (strcmp(vms->fn, fn2)) {
08003             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
08004          }
08005       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
08006          /* Move to old folder before deleting */
08007          res = save_to_folder(vmu, vms, x, 1);
08008          if (res == ERROR_LOCK_PATH) {
08009             /* If save failed do not delete the message */
08010             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
08011             vms->deleted[x] = 0;
08012             vms->heard[x] = 0;
08013             --x;
08014          }
08015       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
08016          /* Move to deleted folder */
08017          res = save_to_folder(vmu, vms, x, 10);
08018          if (res == ERROR_LOCK_PATH) {
08019             /* If save failed do not delete the message */
08020             vms->deleted[x] = 0;
08021             vms->heard[x] = 0;
08022             --x;
08023          }
08024       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
08025          /* If realtime storage enabled - we should explicitly delete this message,
08026          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
08027          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08028          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08029             DELETE(vms->curdir, x, vms->fn, vmu);
08030          }
08031       }
08032    }
08033 
08034    /* Delete ALL remaining messages */
08035    nummsg = x - 1;
08036    for (x = vms->curmsg + 1; x <= nummsg; x++) {
08037       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
08038       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
08039          DELETE(vms->curdir, x, vms->fn, vmu);
08040       }
08041    }
08042    ast_unlock_path(vms->curdir);
08043 #else /* defined(IMAP_STORAGE) */
08044    ast_mutex_lock(&vms->lock);
08045    if (vms->deleted) {
08046       /* Since we now expunge after each delete, deleting in reverse order
08047        * ensures that no reordering occurs between each step. */
08048       last_msg_idx = vms->dh_arraysize;
08049       for (x = last_msg_idx - 1; x >= 0; x--) {
08050          if (vms->deleted[x]) {
08051             ast_debug(3, "IMAP delete of %d\n", x);
08052             DELETE(vms->curdir, x, vms->fn, vmu);
08053          }
08054       }
08055    }
08056 #endif
08057 
08058 done:
08059    if (vms->deleted) {
08060       ast_free(vms->deleted);
08061       vms->deleted = NULL;
08062    }
08063    if (vms->heard) {
08064       ast_free(vms->heard);
08065       vms->heard = NULL;
08066    }
08067    vms->dh_arraysize = 0;
08068 #ifdef IMAP_STORAGE
08069    ast_mutex_unlock(&vms->lock);
08070 #endif
08071 
08072    return 0;
08073 }

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

Definition at line 11147 of file app_voicemail_imapstorage.c.

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

11148 {
11149    int which = 0;
11150    int wordlen;
11151    struct ast_vm_user *vmu;
11152    const char *context = "";
11153 
11154    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
11155    if (pos > 4)
11156       return NULL;
11157    if (pos == 3)
11158       return (state == 0) ? ast_strdup("for") : NULL;
11159    wordlen = strlen(word);
11160    AST_LIST_TRAVERSE(&users, vmu, list) {
11161       if (!strncasecmp(word, vmu->context, wordlen)) {
11162          if (context && strcmp(context, vmu->context) && ++which > state)
11163             return ast_strdup(vmu->context);
11164          /* ignore repeated contexts ? */
11165          context = vmu->context;
11166       }
11167    }
11168    return NULL;
11169 }

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

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

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

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

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

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

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

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

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

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

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

13178 {
13179    int cmd = 0;
13180    char destination[80] = "";
13181    int retries = 0;
13182 
13183    if (!num) {
13184       ast_verb(3, "Destination number will be entered manually\n");
13185       while (retries < 3 && cmd != 't') {
13186          destination[1] = '\0';
13187          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
13188          if (!cmd)
13189             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
13190          if (!cmd)
13191             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
13192          if (!cmd) {
13193             cmd = ast_waitfordigit(chan, 6000);
13194             if (cmd)
13195                destination[0] = cmd;
13196          }
13197          if (!cmd) {
13198             retries++;
13199          } else {
13200 
13201             if (cmd < 0)
13202                return 0;
13203             if (cmd == '*') {
13204                ast_verb(3, "User hit '*' to cancel outgoing call\n");
13205                return 0;
13206             }
13207             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
13208                retries++;
13209             else
13210                cmd = 't';
13211          }
13212          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
13213       }
13214       if (retries >= 3) {
13215          return 0;
13216       }
13217       
13218    } else {
13219       if (option_verbose > 2)
13220          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
13221       ast_copy_string(destination, num, sizeof(destination));
13222    }
13223 
13224    if (!ast_strlen_zero(destination)) {
13225       if (destination[strlen(destination) -1 ] == '*')
13226          return 0; 
13227       if (option_verbose > 2)
13228          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
13229       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
13230       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
13231       chan->priority = 0;
13232       return 9;
13233    }
13234    return 0;
13235 }

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

Definition at line 10730 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.

10731 {
10732    struct ast_vm_user *vmu;
10733 
10734    if (!ast_strlen_zero(box) && box[0] == '*') {
10735       ast_log(LOG_WARNING, "Mailbox %s in context %s begins with '*' character.  The '*' character,"
10736             "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10737             "\n\tpredefined extension 'a'.  A mailbox or password beginning with '*' is not valid"
10738             "\n\tand will be ignored.\n", box, context);
10739       return NULL;
10740    }
10741 
10742    AST_LIST_TRAVERSE(&users, vmu, list) {
10743       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10744          if (strcasecmp(vmu->context, context)) {
10745             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10746                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10747                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10748                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10749          }
10750          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10751          return NULL;
10752       }
10753       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10754          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10755          return NULL;
10756       }
10757    }
10758    
10759    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10760       return NULL;
10761    
10762    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10763    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10764 
10765    AST_LIST_INSERT_TAIL(&users, vmu, list);
10766    
10767    return vmu;
10768 }

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

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

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

11762 {
11763    struct ast_vm_user *current;
11764    AST_LIST_LOCK(&users);
11765    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11766       ast_set_flag(current, VM_ALLOCED);
11767       free_user(current);
11768    }
11769    AST_LIST_UNLOCK(&users);
11770 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11773 of file app_voicemail_imapstorage.c.

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

11774 {
11775    struct vm_zone *zcur;
11776    AST_LIST_LOCK(&zones);
11777    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11778       free_zone(zcur);
11779    AST_LIST_UNLOCK(&zones);
11780 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 5087 of file app_voicemail_imapstorage.c.

References ast_free.

05088 {
05089    ast_free(z);
05090 }

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

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

05044 {
05045    struct ast_tm tm;
05046    struct timeval t = ast_tvnow();
05047    
05048    ast_localtime(&t, &tm, "UTC");
05049 
05050    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
05051 }

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

06776 {
06777    int x;
06778    int d;
06779    char fn[PATH_MAX];
06780    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06781    if (d)
06782       return d;
06783    for (x = start; x < 5; x++) { /* For all folders */
06784       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06785          return d;
06786       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06787       if (d)
06788          return d;
06789       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06790 
06791       /* The inbox folder can have its name changed under certain conditions
06792        * so this checks if the sound file exists for the inbox folder name and
06793        * if it doesn't, plays the default name instead. */
06794       if (x == 0) {
06795          if (ast_fileexists(fn, NULL, NULL)) {
06796             d = vm_play_folder_name(chan, fn);
06797          } else {
06798             ast_verb(1, "failed to find %s\n", fn);
06799             d = vm_play_folder_name(chan, "vm-INBOX");
06800          }
06801       } else {
06802          ast_test_suite_event_notify("PLAYBACK", "Message: folder name %s", fn);
06803          d = vm_play_folder_name(chan, fn);
06804       }
06805 
06806       if (d)
06807          return d;
06808       d = ast_waitfordigit(chan, 500);
06809       if (d)
06810          return d;
06811    }
06812 
06813    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06814    if (d)
06815       return d;
06816    d = ast_waitfordigit(chan, 4000);
06817    return d;
06818 }

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

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

06833 {
06834    int res = 0;
06835    int loops = 0;
06836 
06837    res = ast_play_and_wait(chan, fn);  /* Folder name */
06838    while (((res < '0') || (res > '9')) &&
06839          (res != '#') && (res >= 0) &&
06840          loops < 4) {
06841       res = get_folder(chan, 0);
06842       loops++;
06843    }
06844    if (loops == 4) { /* give up */
06845       ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", '#', '#');
06846       return '#';
06847    }
06848    ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", res, res);
06849    return res;
06850 }

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

11532 {
11533    unsigned int len;
11534    struct mwi_sub *mwi_sub;
11535    struct mwi_sub_task *p = datap;
11536 
11537    len = sizeof(*mwi_sub);
11538    if (!ast_strlen_zero(p->mailbox))
11539       len += strlen(p->mailbox);
11540 
11541    if (!ast_strlen_zero(p->context))
11542       len += strlen(p->context) + 1; /* Allow for seperator */
11543 
11544    if (!(mwi_sub = ast_calloc(1, len)))
11545       return -1;
11546 
11547    mwi_sub->uniqueid = p->uniqueid;
11548    if (!ast_strlen_zero(p->mailbox))
11549       strcpy(mwi_sub->mailbox, p->mailbox);
11550 
11551    if (!ast_strlen_zero(p->context)) {
11552       strcat(mwi_sub->mailbox, "@");
11553       strcat(mwi_sub->mailbox, p->context);
11554    }
11555 
11556    AST_RWLIST_WRLOCK(&mwi_subs);
11557    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11558    AST_RWLIST_UNLOCK(&mwi_subs);
11559    ast_free((void *) p->mailbox);
11560    ast_free((void *) p->context);
11561    ast_free(p);
11562    poll_subscribed_mailbox(mwi_sub);
11563    return 0;
11564 }

static int handle_unsubscribe ( void *  datap  )  [static]

Definition at line 11509 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.

11510 {
11511    struct mwi_sub *mwi_sub;
11512    uint32_t *uniqueid = datap;
11513    
11514    AST_RWLIST_WRLOCK(&mwi_subs);
11515    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11516       if (mwi_sub->uniqueid == *uniqueid) {
11517          AST_LIST_REMOVE_CURRENT(entry);
11518          break;
11519       }
11520    }
11521    AST_RWLIST_TRAVERSE_SAFE_END
11522    AST_RWLIST_UNLOCK(&mwi_subs);
11523 
11524    if (mwi_sub)
11525       mwi_sub_destroy(mwi_sub);
11526 
11527    ast_free(uniqueid);  
11528    return 0;
11529 }

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

11285 {
11286    switch (cmd) {
11287    case CLI_INIT:
11288       e->command = "voicemail reload";
11289       e->usage =
11290          "Usage: voicemail reload\n"
11291          "       Reload voicemail configuration\n";
11292       return NULL;
11293    case CLI_GENERATE:
11294       return NULL;
11295    }
11296 
11297    if (a->argc != 2)
11298       return CLI_SHOWUSAGE;
11299 
11300    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11301    load_config(1);
11302    
11303    return CLI_SUCCESS;
11304 }

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

11173 {
11174    struct ast_vm_user *vmu;
11175 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11176    const char *context = NULL;
11177    int users_counter = 0;
11178 
11179    switch (cmd) {
11180    case CLI_INIT:
11181       e->command = "voicemail show users";
11182       e->usage =
11183          "Usage: voicemail show users [for <context>]\n"
11184          "       Lists all mailboxes currently set up\n";
11185       return NULL;
11186    case CLI_GENERATE:
11187       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
11188    }  
11189 
11190    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
11191       return CLI_SHOWUSAGE;
11192    if (a->argc == 5) {
11193       if (strcmp(a->argv[3],"for"))
11194          return CLI_SHOWUSAGE;
11195       context = a->argv[4];
11196    }
11197 
11198    if (ast_check_realtime("voicemail")) {
11199       if (!context) {
11200          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
11201          return CLI_SHOWUSAGE;
11202       }
11203       return show_users_realtime(a->fd, context);
11204    }
11205 
11206    AST_LIST_LOCK(&users);
11207    if (AST_LIST_EMPTY(&users)) {
11208       ast_cli(a->fd, "There are no voicemail users currently defined\n");
11209       AST_LIST_UNLOCK(&users);
11210       return CLI_FAILURE;
11211    }
11212    if (!context) {
11213       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11214    } else {
11215       int count = 0;
11216       AST_LIST_TRAVERSE(&users, vmu, list) {
11217          if (!strcmp(context, vmu->context)) {
11218             count++;
11219             break;
11220          }
11221       }
11222       if (count) {
11223          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
11224       } else {
11225          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
11226          AST_LIST_UNLOCK(&users);
11227          return CLI_FAILURE;
11228       }
11229    }
11230    AST_LIST_TRAVERSE(&users, vmu, list) {
11231       int newmsgs = 0, oldmsgs = 0;
11232       char count[12], tmp[256] = "";
11233 
11234       if (!context || !strcmp(context, vmu->context)) {
11235          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
11236          inboxcount(tmp, &newmsgs, &oldmsgs);
11237          snprintf(count, sizeof(count), "%d", newmsgs);
11238          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
11239          users_counter++;
11240       }
11241    }
11242    AST_LIST_UNLOCK(&users);
11243    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
11244    return CLI_SUCCESS;
11245 }

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

11249 {
11250    struct vm_zone *zone;
11251 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11252    char *res = CLI_SUCCESS;
11253 
11254    switch (cmd) {
11255    case CLI_INIT:
11256       e->command = "voicemail show zones";
11257       e->usage =
11258          "Usage: voicemail show zones\n"
11259          "       Lists zone message formats\n";
11260       return NULL;
11261    case CLI_GENERATE:
11262       return NULL;
11263    }
11264 
11265    if (a->argc != 3)
11266       return CLI_SHOWUSAGE;
11267 
11268    AST_LIST_LOCK(&zones);
11269    if (!AST_LIST_EMPTY(&zones)) {
11270       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
11271       AST_LIST_TRAVERSE(&zones, zone, list) {
11272          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
11273       }
11274    } else {
11275       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
11276       res = CLI_FAILURE;
11277    }
11278    AST_LIST_UNLOCK(&zones);
11279 
11280    return res;
11281 }

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

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

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

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

Definition at line 5513 of file app_voicemail_imapstorage.c.

References inboxcount2().

05514 {
05515    int urgentmsgs = 0;
05516    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05517    if (newmsgs) {
05518       *newmsgs += urgentmsgs;
05519    }
05520    return res;
05521 }

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

Definition at line 5454 of file app_voicemail_imapstorage.c.

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

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

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

utility used by inchar(), for base_encode()

Definition at line 4213 of file app_voicemail_imapstorage.c.

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

04214 {
04215    int l;
04216 
04217    if (bio->ateof)
04218       return 0;
04219 
04220    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04221       if (ferror(fi))
04222          return -1;
04223 
04224       bio->ateof = 1;
04225       return 0;
04226    }
04227 
04228    bio->iolen = l;
04229    bio->iocp = 0;
04230 
04231    return 1;
04232 }

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

utility used by base_encode()

Definition at line 4237 of file app_voicemail_imapstorage.c.

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

04238 {
04239    if (bio->iocp>=bio->iolen) {
04240       if (!inbuf(bio, fi))
04241          return EOF;
04242    }
04243 
04244    return bio->iobuf[bio->iocp++];
04245 }

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

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

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

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

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

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 5586 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, leave_vm_options::exitcontext, 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.

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

static int load_config ( int  reload  )  [static]

Definition at line 11829 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_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, and VOICEMAIL_CONFIG.

11830 {
11831    struct ast_config *cfg, *ucfg;
11832    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11833    int res;
11834 
11835    ast_unload_realtime("voicemail");
11836    ast_unload_realtime("voicemail_data");
11837 
11838    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11839       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11840          return 0;
11841       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11842          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11843          ucfg = NULL;
11844       }
11845       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11846       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11847          ast_config_destroy(ucfg);
11848          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11849          return 0;
11850       }
11851    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11852       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11853       return 0;
11854    } else {
11855       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11856       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11857          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11858          ucfg = NULL;
11859       }
11860    }
11861 
11862    res = actual_load_config(reload, cfg, ucfg);
11863 
11864    ast_config_destroy(cfg);
11865    ast_config_destroy(ucfg);
11866 
11867    return res;
11868 }

static int load_module ( void   )  [static]

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

13130 {
13131    int res;
13132    my_umask = umask(0);
13133    umask(my_umask);
13134 
13135    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
13136       return AST_MODULE_LOAD_DECLINE;
13137    }
13138 
13139    /* compute the location of the voicemail spool directory */
13140    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
13141    
13142    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
13143       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
13144    }
13145 
13146    if ((res = load_config(0)))
13147       return res;
13148 
13149    res = ast_register_application_xml(app, vm_exec);
13150    res |= ast_register_application_xml(app2, vm_execmain);
13151    res |= ast_register_application_xml(app3, vm_box_exists);
13152    res |= ast_register_application_xml(app4, vmauthenticate);
13153    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
13154    res |= ast_custom_function_register(&mailbox_exists_acf);
13155    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
13156 #ifdef TEST_FRAMEWORK
13157    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
13158    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
13159    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
13160    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
13161    res |= AST_TEST_REGISTER(test_voicemail_load_config);
13162 #endif
13163 
13164    if (res)
13165       return res;
13166 
13167    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13168    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
13169 
13170    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
13171    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
13172    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
13173 
13174    return res;
13175 }

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 4530 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(), ast_strftime_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, 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().

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

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

11661 {
11662    struct ast_vm_user *vmu = NULL;
11663    const char *id = astman_get_header(m, "ActionID");
11664    char actionid[128] = "";
11665 
11666    if (!ast_strlen_zero(id))
11667       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11668 
11669    AST_LIST_LOCK(&users);
11670 
11671    if (AST_LIST_EMPTY(&users)) {
11672       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11673       AST_LIST_UNLOCK(&users);
11674       return RESULT_SUCCESS;
11675    }
11676    
11677    astman_send_ack(s, m, "Voicemail user list will follow");
11678    
11679    AST_LIST_TRAVERSE(&users, vmu, list) {
11680       char dirname[256];
11681 
11682 #ifdef IMAP_STORAGE
11683       int new, old;
11684       inboxcount(vmu->mailbox, &new, &old);
11685 #endif
11686       
11687       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11688       astman_append(s,
11689          "%s"
11690          "Event: VoicemailUserEntry\r\n"
11691          "VMContext: %s\r\n"
11692          "VoiceMailbox: %s\r\n"
11693          "Fullname: %s\r\n"
11694          "Email: %s\r\n"
11695          "Pager: %s\r\n"
11696          "ServerEmail: %s\r\n"
11697          "MailCommand: %s\r\n"
11698          "Language: %s\r\n"
11699          "TimeZone: %s\r\n"
11700          "Callback: %s\r\n"
11701          "Dialout: %s\r\n"
11702          "UniqueID: %s\r\n"
11703          "ExitContext: %s\r\n"
11704          "SayDurationMinimum: %d\r\n"
11705          "SayEnvelope: %s\r\n"
11706          "SayCID: %s\r\n"
11707          "AttachMessage: %s\r\n"
11708          "AttachmentFormat: %s\r\n"
11709          "DeleteMessage: %s\r\n"
11710          "VolumeGain: %.2f\r\n"
11711          "CanReview: %s\r\n"
11712          "CallOperator: %s\r\n"
11713          "MaxMessageCount: %d\r\n"
11714          "MaxMessageLength: %d\r\n"
11715          "NewMessageCount: %d\r\n"
11716 #ifdef IMAP_STORAGE
11717          "OldMessageCount: %d\r\n"
11718          "IMAPUser: %s\r\n"
11719 #endif
11720          "\r\n",
11721          actionid,
11722          vmu->context,
11723          vmu->mailbox,
11724          vmu->fullname,
11725          vmu->email,
11726          vmu->pager,
11727          vmu->serveremail,
11728          vmu->mailcmd,
11729          vmu->language,
11730          vmu->zonetag,
11731          vmu->callback,
11732          vmu->dialout,
11733          vmu->uniqueid,
11734          vmu->exit,
11735          vmu->saydurationm,
11736          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11737          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11738          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11739          vmu->attachfmt,
11740          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11741          vmu->volgain,
11742          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11743          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11744          vmu->maxmsg,
11745          vmu->maxsecs,
11746 #ifdef IMAP_STORAGE
11747          new, old, vmu->imapuser
11748 #else
11749          count_messages(vmu, dirname)
11750 #endif
11751          );
11752    }     
11753    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11754 
11755    AST_LIST_UNLOCK(&users);
11756 
11757    return RESULT_SUCCESS;
11758 }

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

Definition at line 11481 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.

11482 {
11483    while (poll_thread_run) {
11484       struct timespec ts = { 0, };
11485       struct timeval wait;
11486 
11487       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11488       ts.tv_sec = wait.tv_sec;
11489       ts.tv_nsec = wait.tv_usec * 1000;
11490 
11491       ast_mutex_lock(&poll_lock);
11492       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11493       ast_mutex_unlock(&poll_lock);
11494 
11495       if (!poll_thread_run)
11496          break;
11497 
11498       poll_subscribed_mailboxes();
11499    }
11500 
11501    return NULL;
11502 }

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

References __has_voicemail().

05381 {
05382    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05383 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11504 of file app_voicemail_imapstorage.c.

References ast_free, and mwi_sub.

11505 {
11506    ast_free(mwi_sub);
11507 }

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

Definition at line 11592 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.

11593 {
11594    struct mwi_sub_task *mwist;
11595    
11596    if (ast_event_get_type(event) != AST_EVENT_SUB)
11597       return;
11598 
11599    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11600       return;
11601 
11602    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11603       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11604       return;
11605    }
11606    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11607    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11608    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11609    
11610    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11611       ast_free(mwist);
11612    }
11613 }

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

Definition at line 11566 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_log(), ast_taskprocessor_push(), handle_unsubscribe(), LOG_ERROR, mwi_subscription_tps, and mwi_sub_task::uniqueid.

11567 {
11568    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11569 
11570    if (!uniqueid) {
11571       ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");
11572       return;
11573    }
11574 
11575    if (ast_event_get_type(event) != AST_EVENT_UNSUB) {
11576       ast_free(uniqueid);
11577       return;
11578    }
11579 
11580    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI) {
11581       ast_free(uniqueid);
11582       return;
11583    }
11584 
11585    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11586    *uniqueid = u;
11587    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11588       ast_free(uniqueid);
11589    }
11590 }

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

07064 {
07065    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
07066    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
07067    const char *category;
07068    char *myserveremail = serveremail;
07069 
07070    ast_channel_lock(chan);
07071    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
07072       category = ast_strdupa(category);
07073    }
07074    ast_channel_unlock(chan);
07075 
07076 #ifndef IMAP_STORAGE
07077    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
07078 #else
07079    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
07080 #endif
07081    make_file(fn, sizeof(fn), todir, msgnum);
07082    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
07083 
07084    if (!ast_strlen_zero(vmu->attachfmt)) {
07085       if (strstr(fmt, vmu->attachfmt))
07086          fmt = vmu->attachfmt;
07087       else
07088          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);
07089    }
07090 
07091    /* Attach only the first format */
07092    fmt = ast_strdupa(fmt);
07093    stringp = fmt;
07094    strsep(&stringp, "|");
07095 
07096    if (!ast_strlen_zero(vmu->serveremail))
07097       myserveremail = vmu->serveremail;
07098 
07099    if (!ast_strlen_zero(vmu->email)) {
07100       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
07101 
07102       if (attach_user_voicemail)
07103          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
07104 
07105       /* XXX possible imap issue, should category be NULL XXX */
07106       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
07107 
07108       if (attach_user_voicemail)
07109          DISPOSE(todir, msgnum);
07110    }
07111 
07112    if (!ast_strlen_zero(vmu->pager)) {
07113       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
07114    }
07115 
07116    if (ast_test_flag(vmu, VM_DELETE))
07117       DELETE(todir, msgnum, fn, vmu);
07118 
07119    /* Leave voicemail for someone */
07120    if (ast_app_has_voicemail(ext_context, NULL)) 
07121       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
07122 
07123    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
07124 
07125    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);
07126    run_externnotify(vmu->context, vmu->mailbox, flag);
07127 
07128 #ifdef IMAP_STORAGE
07129    vm_delete(fn);  /* Delete the file, but not the IMAP message */
07130    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
07131       vm_imap_delete(NULL, vms->curmsg, vmu);
07132       vms->newmessages--;  /* Fix new message count */
07133    }
07134 #endif
07135 
07136    return 0;
07137 }

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

utility used by base_encode()

Definition at line 4250 of file app_voicemail_imapstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

04251 {
04252    if (bio->linelength >= BASELINELEN) {
04253       if (fputs(ENDL, so) == EOF) {
04254          return -1;
04255       }
04256 
04257       bio->linelength = 0;
04258    }
04259 
04260    if (putc(((unsigned char) c), so) == EOF) {
04261       return -1;
04262    }
04263 
04264    bio->linelength++;
04265 
04266    return 1;
04267 }

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

Definition at line 7912 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.

07913 {
07914    int count_msg, last_msg;
07915 
07916    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07917 
07918    /* Rename the member vmbox HERE so that we don't try to return before
07919     * we know what's going on.
07920     */
07921    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07922 
07923    /* Faster to make the directory than to check if it exists. */
07924    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07925 
07926    /* traverses directory using readdir (or select query for ODBC) */
07927    count_msg = count_messages(vmu, vms->curdir);
07928    if (count_msg < 0) {
07929       return count_msg;
07930    } else {
07931       vms->lastmsg = count_msg - 1;
07932    }
07933 
07934    if (vm_allocate_dh(vms, vmu, count_msg)) {
07935       return -1;
07936    }
07937 
07938    /*
07939    The following test is needed in case sequencing gets messed up.
07940    There appears to be more than one way to mess up sequence, so
07941    we will not try to find all of the root causes--just fix it when
07942    detected.
07943    */
07944 
07945    if (vm_lock_path(vms->curdir)) {
07946       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07947       return ERROR_LOCK_PATH;
07948    }
07949 
07950    /* for local storage, checks directory for messages up to maxmsg limit */
07951    last_msg = last_message_index(vmu, vms->curdir);
07952    ast_unlock_path(vms->curdir);
07953 
07954    if (last_msg < -1) {
07955       return last_msg;
07956    } else if (vms->lastmsg != last_msg) {
07957       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);
07958       resequence_mailbox(vmu, vms->curdir, count_msg);
07959    }
07960 
07961    return 0;
07962 }

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

Definition at line 7686 of file app_voicemail_imapstorage.c.

References adsi_message(), ast_config_destroy(), ast_config_load, AST_DIGIT_ANY, ast_fileexists(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_say_number(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_test_suite_event_notify, ast_variable_retrieve(), CONFIG_FLAG_NOCACHE, 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().

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

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

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

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

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

Definition at line 7483 of file app_voicemail_imapstorage.c.

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

07484 {
07485    int res = 0;
07486 
07487    if (!ast_strlen_zero(category))
07488       res = ast_play_and_wait(chan, category);
07489 
07490    if (res) {
07491       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07492       res = 0;
07493    }
07494 
07495    return res;
07496 }

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

Definition at line 7498 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.

07499 {
07500    int res = 0;
07501    struct vm_zone *the_zone = NULL;
07502    time_t t;
07503 
07504    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07505       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07506       return 0;
07507    }
07508 
07509    /* Does this user have a timezone specified? */
07510    if (!ast_strlen_zero(vmu->zonetag)) {
07511       /* Find the zone in the list */
07512       struct vm_zone *z;
07513       AST_LIST_LOCK(&zones);
07514       AST_LIST_TRAVERSE(&zones, z, list) {
07515          if (!strcmp(z->name, vmu->zonetag)) {
07516             the_zone = z;
07517             break;
07518          }
07519       }
07520       AST_LIST_UNLOCK(&zones);
07521    }
07522 
07523 /* No internal variable parsing for now, so we'll comment it out for the time being */
07524 #if 0
07525    /* Set the DIFF_* variables */
07526    ast_localtime(&t, &time_now, NULL);
07527    tv_now = ast_tvnow();
07528    ast_localtime(&tv_now, &time_then, NULL);
07529 
07530    /* Day difference */
07531    if (time_now.tm_year == time_then.tm_year)
07532       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07533    else
07534       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07535    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07536 
07537    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07538 #endif
07539    if (the_zone) {
07540       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07541    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07542       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07543    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07544       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07545    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07546       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);
07547    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07548       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07549    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07550       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07551    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07552       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07553    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07554       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);
07555    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07556       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07557    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07558       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07559    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07560       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);
07561    } else {
07562       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07563    }
07564 #if 0
07565    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07566 #endif
07567    return res;
07568 }

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

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

07637 {
07638    int res = 0;
07639    int durationm;
07640    int durations;
07641    /* Verify that we have a duration for the message */
07642    if (duration == NULL)
07643       return res;
07644 
07645    /* Convert from seconds to minutes */
07646    durations = atoi(duration);
07647    durationm = (durations / 60);
07648 
07649    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07650 
07651    if ((!res) && (durationm >= minduration)) {
07652       res = wait_file2(chan, vms, "vm-duration");
07653 
07654       /* POLISH syntax */
07655       if (!strncasecmp(chan->language, "pl", 2)) {
07656          div_t num = div(durationm, 10);
07657 
07658          if (durationm == 1) {
07659             res = ast_play_and_wait(chan, "digits/1z");
07660             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07661          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07662             if (num.rem == 2) {
07663                if (!num.quot) {
07664                   res = ast_play_and_wait(chan, "digits/2-ie");
07665                } else {
07666                   res = say_and_wait(chan, durationm - 2 , chan->language);
07667                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07668                }
07669             } else {
07670                res = say_and_wait(chan, durationm, chan->language);
07671             }
07672             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07673          } else {
07674             res = say_and_wait(chan, durationm, chan->language);
07675             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07676          }
07677       /* DEFAULT syntax */
07678       } else {
07679          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07680          res = wait_file2(chan, vms, "vm-minutes");
07681       }
07682    }
07683    return res;
07684 }

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

13445 {
13446    /* Record message & let caller review or re-record it, or set options if applicable */
13447    int res = 0;
13448    int cmd = 0;
13449    int max_attempts = 3;
13450    int attempts = 0;
13451    int recorded = 0;
13452    int msg_exists = 0;
13453    signed char zero_gain = 0;
13454    char tempfile[PATH_MAX];
13455    char *acceptdtmf = "#";
13456    char *canceldtmf = "";
13457    int canceleddtmf = 0;
13458 
13459    /* Note that urgent and private are for flagging messages as such in the future */
13460 
13461    /* barf if no pointer passed to store duration in */
13462    if (duration == NULL) {
13463       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
13464       return -1;
13465    }
13466 
13467    if (!outsidecaller)
13468       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
13469    else
13470       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
13471 
13472    cmd = '3';  /* Want to start by recording */
13473 
13474    while ((cmd >= 0) && (cmd != 't')) {
13475       switch (cmd) {
13476       case '1':
13477          if (!msg_exists) {
13478             /* In this case, 1 is to record a message */
13479             cmd = '3';
13480             break;
13481          } else {
13482             /* Otherwise 1 is to save the existing message */
13483             ast_verb(3, "Saving message as is\n");
13484             if (!outsidecaller) 
13485                ast_filerename(tempfile, recordfile, NULL);
13486             ast_stream_and_wait(chan, "vm-msgsaved", "");
13487             if (!outsidecaller) {
13488                /* Saves to IMAP server only if imapgreeting=yes */
13489                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
13490                DISPOSE(recordfile, -1);
13491             }
13492             cmd = 't';
13493             return res;
13494          }
13495       case '2':
13496          /* Review */
13497          ast_verb(3, "Reviewing the message\n");
13498          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13499          break;
13500       case '3':
13501          msg_exists = 0;
13502          /* Record */
13503          if (recorded == 1) 
13504             ast_verb(3, "Re-recording the message\n");
13505          else  
13506             ast_verb(3, "Recording the message\n");
13507          
13508          if (recorded && outsidecaller) {
13509             cmd = ast_play_and_wait(chan, INTRO);
13510             cmd = ast_play_and_wait(chan, "beep");
13511          }
13512          recorded = 1;
13513          /* 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 */
13514          if (record_gain)
13515             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13516          if (ast_test_flag(vmu, VM_OPERATOR))
13517             canceldtmf = "0";
13518          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13519          if (strchr(canceldtmf, cmd)) {
13520          /* need this flag here to distinguish between pressing '0' during message recording or after */
13521             canceleddtmf = 1;
13522          }
13523          if (record_gain)
13524             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13525          if (cmd == -1) {
13526             /* User has hung up, no options to give */
13527             if (!outsidecaller) {
13528                /* user was recording a greeting and they hung up, so let's delete the recording. */
13529                ast_filedelete(tempfile, NULL);
13530             }     
13531             return cmd;
13532          }
13533          if (cmd == '0') {
13534             break;
13535          } else if (cmd == '*') {
13536             break;
13537 #if 0
13538          } else if (vmu->review && sound_duration && (*sound_duration < 5)) {
13539             /* Message is too short */
13540             ast_verb(3, "Message too short\n");
13541             cmd = ast_play_and_wait(chan, "vm-tooshort");
13542             cmd = ast_filedelete(tempfile, NULL);
13543             break;
13544          } else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
13545             /* Message is all silence */
13546             ast_verb(3, "Nothing recorded\n");
13547             cmd = ast_filedelete(tempfile, NULL);
13548             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13549             if (!cmd)
13550                cmd = ast_play_and_wait(chan, "vm-speakup");
13551             break;
13552 #endif
13553          } else {
13554             /* If all is well, a message exists */
13555             msg_exists = 1;
13556             cmd = 0;
13557          }
13558          break;
13559       case '4':
13560          if (outsidecaller) {  /* only mark vm messages */
13561             /* Mark Urgent */
13562             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13563                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
13564                res = ast_play_and_wait(chan, "vm-marked-urgent");
13565                strcpy(flag, "Urgent");
13566             } else if (flag) {
13567                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
13568                res = ast_play_and_wait(chan, "vm-urgent-removed");
13569                strcpy(flag, "");
13570             } else {
13571                ast_play_and_wait(chan, "vm-sorry");
13572             }
13573             cmd = 0;
13574          } else {
13575             cmd = ast_play_and_wait(chan, "vm-sorry");
13576          }
13577          break;
13578       case '5':
13579       case '6':
13580       case '7':
13581       case '8':
13582       case '9':
13583       case '*':
13584       case '#':
13585          cmd = ast_play_and_wait(chan, "vm-sorry");
13586          break;
13587 #if 0 
13588 /*  XXX Commented out for the moment because of the dangers of deleting
13589     a message while recording (can put the message numbers out of sync) */
13590       case '*':
13591          /* Cancel recording, delete message, offer to take another message*/
13592          cmd = ast_play_and_wait(chan, "vm-deleted");
13593          cmd = ast_filedelete(tempfile, NULL);
13594          if (outsidecaller) {
13595             res = vm_exec(chan, NULL);
13596             return res;
13597          }
13598          else
13599             return 1;
13600 #endif
13601       case '0':
13602          if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13603             cmd = ast_play_and_wait(chan, "vm-sorry");
13604             break;
13605          }
13606          if (msg_exists || recorded) {
13607             cmd = ast_play_and_wait(chan, "vm-saveoper");
13608             if (!cmd)
13609                cmd = ast_waitfordigit(chan, 3000);
13610             if (cmd == '1') {
13611                ast_filerename(tempfile, recordfile, NULL);
13612                ast_play_and_wait(chan, "vm-msgsaved");
13613                cmd = '0';
13614             } else if (cmd == '4') {
13615                if (flag) {
13616                   ast_play_and_wait(chan, "vm-marked-urgent");
13617                   strcpy(flag, "Urgent");
13618                }
13619                ast_play_and_wait(chan, "vm-msgsaved");
13620                cmd = '0';
13621             } else {
13622                ast_play_and_wait(chan, "vm-deleted");
13623                DELETE(tempfile, -1, tempfile, vmu);
13624                cmd = '0';
13625             }
13626          }
13627          return cmd;
13628       default:
13629          /* If the caller is an ouside caller, and the review option is enabled,
13630             allow them to review the message, but let the owner of the box review
13631             their OGM's */
13632          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13633             return cmd;
13634          if (msg_exists) {
13635             cmd = ast_play_and_wait(chan, "vm-review");
13636             if (!cmd && outsidecaller) {
13637                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13638                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
13639                } else if (flag) {
13640                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13641                }
13642             }
13643          } else {
13644             cmd = ast_play_and_wait(chan, "vm-torerecord");
13645             if (!cmd)
13646                cmd = ast_waitfordigit(chan, 600);
13647          }
13648          
13649          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13650             cmd = ast_play_and_wait(chan, "vm-reachoper");
13651             if (!cmd)
13652                cmd = ast_waitfordigit(chan, 600);
13653          }
13654 #if 0
13655          if (!cmd)
13656             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13657 #endif
13658          if (!cmd)
13659             cmd = ast_waitfordigit(chan, 6000);
13660          if (!cmd) {
13661             attempts++;
13662          }
13663          if (attempts > max_attempts) {
13664             cmd = 't';
13665          }
13666       }
13667    }
13668    if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13669       /* Hang up or timeout, so delete the recording. */
13670       ast_filedelete(tempfile, NULL);
13671    }
13672 
13673    if (cmd != 't' && outsidecaller)
13674       ast_play_and_wait(chan, "vm-goodbye");
13675 
13676    return cmd;
13677 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11453 of file app_voicemail_imapstorage.c.

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

11454 {
11455    int new = 0, old = 0, urgent = 0;
11456 
11457    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11458 
11459    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11460       mwi_sub->old_urgent = urgent;
11461       mwi_sub->old_new = new;
11462       mwi_sub->old_old = old;
11463       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11464       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11465    }
11466 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

11469 {
11470    struct mwi_sub *mwi_sub;
11471 
11472    AST_RWLIST_RDLOCK(&mwi_subs);
11473    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11474       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11475          poll_subscribed_mailbox(mwi_sub);
11476       }
11477    }
11478    AST_RWLIST_UNLOCK(&mwi_subs);
11479 }

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 4338 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, 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.

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

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

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

07027 {
07028    struct ast_event *event;
07029    char *mailbox, *context;
07030 
07031    /* Strip off @default */
07032    context = mailbox = ast_strdupa(box);
07033    strsep(&context, "@");
07034    if (ast_strlen_zero(context))
07035       context = "default";
07036 
07037    if (!(event = ast_event_new(AST_EVENT_MWI,
07038          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07039          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07040          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
07041          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
07042          AST_EVENT_IE_END))) {
07043       return;
07044    }
07045 
07046    ast_event_queue_and_cache(event);
07047 }

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

Definition at line 12559 of file app_voicemail_imapstorage.c.

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

12559                                                                                            {
12560    struct ast_config *pwconf;
12561    struct ast_flags config_flags = { 0 };
12562 
12563    pwconf = ast_config_load(secretfn, config_flags);
12564    if (pwconf) {
12565       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12566       if (val) {
12567          ast_copy_string(password, val, passwordlen);
12568          ast_config_destroy(pwconf);
12569          return;
12570       }
12571       ast_config_destroy(pwconf);
12572    }
12573    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12574 }

static int reload ( void   )  [static]

Definition at line 13089 of file app_voicemail_imapstorage.c.

References load_config().

13090 {
13091    return load_config(1);
13092 }

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

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

04009 {
04010    char stxt[PATH_MAX];
04011    char dtxt[PATH_MAX];
04012    ast_filerename(sfn, dfn, NULL);
04013    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
04014    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
04015    if (ast_check_realtime("voicemail_data")) {
04016       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
04017    }
04018    rename(stxt, dtxt);
04019 }

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

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

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

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

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

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

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

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

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

Definition at line 6182 of file app_voicemail_imapstorage.c.

References AST_DIGIT_ANY, and ast_say_number().

06183 {
06184    int d;
06185    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06186    return d;
06187 }

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

Definition at line 12545 of file app_voicemail_imapstorage.c.

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

12546 {
12547    int res = -1;
12548    char dir[PATH_MAX];
12549    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12550    ast_debug(2, "About to try retrieving name file %s\n", dir);
12551    RETRIEVE(dir, -1, mailbox, context);
12552    if (ast_fileexists(dir, NULL, NULL)) {
12553       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12554    }
12555    DISPOSE(dir, -1);
12556    return res;
12557 }

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

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

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

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

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

Definition at line 11108 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.

11109 {
11110    struct ast_config *cfg;
11111    const char *cat = NULL;
11112 
11113    if (!(cfg = ast_load_realtime_multientry("voicemail", 
11114       "context", context, SENTINEL))) {
11115       return CLI_FAILURE;
11116    }
11117 
11118    ast_cli(fd,
11119       "\n"
11120       "=============================================================\n"
11121       "=== Configured Voicemail Users ==============================\n"
11122       "=============================================================\n"
11123       "===\n");
11124 
11125    while ((cat = ast_category_browse(cfg, cat))) {
11126       struct ast_variable *var = NULL;
11127       ast_cli(fd,
11128          "=== Mailbox ...\n"
11129          "===\n");
11130       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
11131          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
11132       ast_cli(fd,
11133          "===\n"
11134          "=== ---------------------------------------------------------\n"
11135          "===\n");
11136    }
11137 
11138    ast_cli(fd,
11139       "=============================================================\n"
11140       "\n");
11141 
11142    ast_config_destroy(cfg);
11143 
11144    return CLI_SUCCESS;
11145 }

static void start_poll_thread ( void   )  [static]

Definition at line 11615 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_log(), ast_pthread_create, LOG_ERROR, mb_poll_thread(), mwi_sub_event_cb(), mwi_sub_sub, mwi_unsub_event_cb(), mwi_unsub_sub, poll_thread, and poll_thread_run.

11616 {
11617    int errcode;
11618    mwi_sub_sub = ast_event_subscribe(AST_EVENT_SUB, mwi_sub_event_cb, "Voicemail MWI subscription", NULL,
11619       AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
11620       AST_EVENT_IE_END);
11621 
11622    mwi_unsub_sub = ast_event_subscribe(AST_EVENT_UNSUB, mwi_unsub_event_cb, "Voicemail MWI subscription", NULL,
11623       AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI,
11624       AST_EVENT_IE_END);
11625 
11626    if (mwi_sub_sub)
11627       ast_event_report_subs(mwi_sub_sub);
11628 
11629    poll_thread_run = 1;
11630 
11631    if ((errcode = ast_pthread_create(&poll_thread, NULL, mb_poll_thread, NULL))) {
11632       ast_log(LOG_ERROR, "Could not create thread: %s\n", strerror(errcode));
11633    }
11634 }

static void stop_poll_thread ( void   )  [static]

Definition at line 11636 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.

11637 {
11638    poll_thread_run = 0;
11639 
11640    if (mwi_sub_sub) {
11641       ast_event_unsubscribe(mwi_sub_sub);
11642       mwi_sub_sub = NULL;
11643    }
11644 
11645    if (mwi_unsub_sub) {
11646       ast_event_unsubscribe(mwi_unsub_sub);
11647       mwi_unsub_sub = NULL;
11648    }
11649 
11650    ast_mutex_lock(&poll_lock);
11651    ast_cond_signal(&poll_cond);
11652    ast_mutex_unlock(&poll_lock);
11653 
11654    pthread_join(poll_thread, NULL);
11655 
11656    poll_thread = AST_PTHREADT_NULL;
11657 }

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

11783 {
11784    char *current;
11785 
11786    /* Add 16 for fudge factor */
11787    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11788 
11789    ast_str_reset(str);
11790    
11791    /* Substitute strings \r, \n, and \t into the appropriate characters */
11792    for (current = (char *) value; *current; current++) {
11793       if (*current == '\\') {
11794          current++;
11795          if (!*current) {
11796             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11797             break;
11798          }
11799          switch (*current) {
11800          case '\\':
11801             ast_str_append(&str, 0, "\\");
11802             break;
11803          case 'r':
11804             ast_str_append(&str, 0, "\r");
11805             break;
11806          case 'n':
11807 #ifdef IMAP_STORAGE
11808             if (!str->used || str->str[str->used - 1] != '\r') {
11809                ast_str_append(&str, 0, "\r");
11810             }
11811 #endif
11812             ast_str_append(&str, 0, "\n");
11813             break;
11814          case 't':
11815             ast_str_append(&str, 0, "\t");
11816             break;
11817          default:
11818             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11819             break;
11820          }
11821       } else {
11822          ast_str_append(&str, 0, "%c", *current);
11823       }
11824    }
11825 
11826    return ast_str_buffer(str);
11827 }

static int unload_module ( void   )  [static]

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

13095 {
13096    int res;
13097 
13098    res = ast_unregister_application(app);
13099    res |= ast_unregister_application(app2);
13100    res |= ast_unregister_application(app3);
13101    res |= ast_unregister_application(app4);
13102    res |= ast_unregister_application(sayname_app);
13103    res |= ast_custom_function_unregister(&mailbox_exists_acf);
13104    res |= ast_manager_unregister("VoicemailUsersList");
13105    res |= ast_data_unregister(NULL);
13106 #ifdef TEST_FRAMEWORK
13107    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
13108    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
13109    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
13110    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
13111    res |= AST_TEST_UNREGISTER(test_voicemail_load_config);
13112 #endif
13113    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
13114    ast_uninstall_vm_functions();
13115    ao2_ref(inprocess_container, -1);
13116 
13117    if (poll_thread != AST_PTHREADT_NULL)
13118       stop_poll_thread();
13119 
13120    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
13121    ast_unload_realtime("voicemail");
13122    ast_unload_realtime("voicemail_data");
13123 
13124    free_vm_users();
13125    free_vm_zones();
13126    return res;
13127 }

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_free, 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 
01762    /* remove old allocation */
01763    if (vms->deleted) {
01764       ast_free(vms->deleted);
01765       vms->deleted = NULL;
01766    }
01767    if (vms->heard) {
01768       ast_free(vms->heard);
01769       vms->heard = NULL;
01770    }
01771    vms->dh_arraysize = 0;
01772 
01773    if (arraysize > 0) {
01774       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01775          return -1;
01776       }
01777       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01778          ast_free(vms->deleted);
01779          vms->deleted = NULL;
01780          return -1;
01781       }
01782       vms->dh_arraysize = arraysize;
01783    }
01784 
01785    return 0;
01786 }

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

09787 {
09788    int useadsi = 0, valid = 0, logretries = 0;
09789    char password[AST_MAX_EXTENSION]="", *passptr;
09790    struct ast_vm_user vmus, *vmu = NULL;
09791 
09792    /* If ADSI is supported, setup login screen */
09793    adsi_begin(chan, &useadsi);
09794    if (!skipuser && useadsi)
09795       adsi_login(chan);
09796    ast_test_suite_event_notify("PLAYBACK", "Message: vm-login");
09797    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09798       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09799       return -1;
09800    }
09801 
09802    /* Authenticate them and get their mailbox/password */
09803 
09804    while (!valid && (logretries < max_logins)) {
09805       /* Prompt for, and read in the username */
09806       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09807          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09808          return -1;
09809       }
09810       if (ast_strlen_zero(mailbox)) {
09811          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09812             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09813          } else {
09814             ast_verb(3, "Username not entered\n"); 
09815             return -1;
09816          }
09817       } else if (mailbox[0] == '*') {
09818          /* user entered '*' */
09819          ast_verb(4, "Mailbox begins with '*', attempting jump to extension 'a'\n");
09820          if (ast_exists_extension(chan, chan->context, "a", 1,
09821             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09822             return -1;
09823          }
09824          ast_verb(4, "Jump to extension 'a' failed; setting mailbox to NULL\n");
09825          mailbox[0] = '\0';
09826       }
09827 
09828       if (useadsi)
09829          adsi_password(chan);
09830 
09831       if (!ast_strlen_zero(prefix)) {
09832          char fullusername[80] = "";
09833          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09834          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09835          ast_copy_string(mailbox, fullusername, mailbox_size);
09836       }
09837 
09838       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09839       vmu = find_user(&vmus, context, mailbox);
09840       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09841          /* saved password is blank, so don't bother asking */
09842          password[0] = '\0';
09843       } else {
09844          ast_test_suite_event_notify("PLAYBACK", "Message: %s", vm_password);
09845          if (ast_streamfile(chan, vm_password, chan->language)) {
09846             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09847             return -1;
09848          }
09849          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09850             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09851             return -1;
09852          } else if (password[0] == '*') {
09853             /* user entered '*' */
09854             ast_verb(4, "Password begins with '*', attempting jump to extension 'a'\n");
09855             if (ast_exists_extension(chan, chan->context, "a", 1,
09856                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09857                mailbox[0] = '*';
09858                return -1;
09859             }
09860             ast_verb(4, "Jump to extension 'a' failed; setting mailbox and user to NULL\n");
09861             mailbox[0] = '\0';
09862             /* if the password entered was '*', do not let a user mailbox be created if the extension 'a' is not defined */
09863             vmu = NULL;
09864          }
09865       }
09866 
09867       if (vmu) {
09868          passptr = vmu->password;
09869          if (passptr[0] == '-') passptr++;
09870       }
09871       if (vmu && !strcmp(passptr, password))
09872          valid++;
09873       else {
09874          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09875          if (!ast_strlen_zero(prefix))
09876             mailbox[0] = '\0';
09877       }
09878       logretries++;
09879       if (!valid) {
09880          if (skipuser || logretries >= max_logins) {
09881             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect");
09882             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09883                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09884                return -1;
09885             }
09886          } else {
09887             ast_test_suite_event_notify("PLAYBACK", "Message: vm-incorrect-mailbox");
09888             if (useadsi)
09889                adsi_login(chan);
09890             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09891                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09892                return -1;
09893             }
09894          }
09895          if (ast_waitstream(chan, "")) /* Channel is hung up */
09896             return -1;
09897       }
09898    }
09899    if (!valid && (logretries >= max_logins)) {
09900       ast_stopstream(chan);
09901       ast_play_and_wait(chan, "vm-goodbye");
09902       return -1;
09903    }
09904    if (vmu && !skipuser) {
09905       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09906    }
09907    return 0;
09908 }

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

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

11004 {
11005    struct ast_vm_user svm;
11006    char *context, *box;
11007    AST_DECLARE_APP_ARGS(args,
11008       AST_APP_ARG(mbox);
11009       AST_APP_ARG(options);
11010    );
11011    static int dep_warning = 0;
11012 
11013    if (ast_strlen_zero(data)) {
11014       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
11015       return -1;
11016    }
11017 
11018    if (!dep_warning) {
11019       dep_warning = 1;
11020       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
11021    }
11022 
11023    box = ast_strdupa(data);
11024 
11025    AST_STANDARD_APP_ARGS(args, box);
11026 
11027    if (args.options) {
11028    }
11029 
11030    if ((context = strchr(args.mbox, '@'))) {
11031       *context = '\0';
11032       context++;
11033    }
11034 
11035    if (find_user(&svm, context, args.mbox)) {
11036       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
11037    } else
11038       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
11039 
11040    return 0;
11041 }

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

09764 {
09765    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09766       return vm_browse_messages_es(chan, vms, vmu);
09767    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09768       return vm_browse_messages_gr(chan, vms, vmu);
09769    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09770       return vm_browse_messages_he(chan, vms, vmu);
09771    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09772       return vm_browse_messages_it(chan, vms, vmu);
09773    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09774       return vm_browse_messages_pt(chan, vms, vmu);
09775    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09776       return vm_browse_messages_vi(chan, vms, vmu);
09777    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09778       return vm_browse_messages_zh(chan, vms, vmu);
09779    } else {                                             /* Default to English syntax */
09780       return vm_browse_messages_en(chan, vms, vmu);
09781    }
09782 }

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

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

09603 {
09604    int cmd = 0;
09605 
09606    if (vms->lastmsg > -1) {
09607       cmd = play_message(chan, vmu, vms);
09608    } else {
09609       cmd = ast_play_and_wait(chan, "vm-youhave");
09610       if (!cmd) 
09611          cmd = ast_play_and_wait(chan, "vm-no");
09612       if (!cmd) {
09613          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09614          cmd = ast_play_and_wait(chan, vms->fn);
09615       }
09616       if (!cmd)
09617          cmd = ast_play_and_wait(chan, "vm-messages");
09618    }
09619    return cmd;
09620 }

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

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

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

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

09551 {
09552    int cmd = 0;
09553 
09554    if (vms->lastmsg > -1) {
09555       cmd = play_message(chan, vmu, vms);
09556    } else {
09557       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09558       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09559          if (!cmd) {
09560             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09561             cmd = ast_play_and_wait(chan, vms->fn);
09562          }
09563          if (!cmd)
09564             cmd = ast_play_and_wait(chan, "vm-messages");
09565       } else {
09566          if (!cmd)
09567             cmd = ast_play_and_wait(chan, "vm-messages");
09568          if (!cmd) {
09569             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09570             cmd = ast_play_and_wait(chan, vms->fn);
09571          }
09572       }
09573    } 
09574    return cmd;
09575 }

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

Definition at line 9578 of file app_voicemail_imapstorage.c.

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

09579 {
09580    int cmd = 0;
09581 
09582    if (vms->lastmsg > -1) {
09583       cmd = play_message(chan, vmu, vms);
09584    } else {
09585       if (!strcasecmp(vms->fn, "INBOX")) {
09586          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09587       } else {
09588          cmd = ast_play_and_wait(chan, "vm-nomessages");
09589       }
09590    }
09591    return cmd;
09592 }

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

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

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

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

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

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

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

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

09737 {
09738    int cmd = 0;
09739 
09740    if (vms->lastmsg > -1) {
09741       cmd = play_message(chan, vmu, vms);
09742    } else {
09743       cmd = ast_play_and_wait(chan, "vm-no");
09744       if (!cmd) {
09745          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09746          cmd = ast_play_and_wait(chan, vms->fn);
09747       }
09748    }
09749    return cmd;
09750 }

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

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

09709 {
09710    int cmd;
09711 
09712    if (vms->lastmsg > -1) {
09713       cmd = play_message(chan, vmu, vms);
09714    } else {
09715       cmd = ast_play_and_wait(chan, "vm-you");
09716       if (!cmd) 
09717          cmd = ast_play_and_wait(chan, "vm-haveno");
09718       if (!cmd)
09719          cmd = ast_play_and_wait(chan, "vm-messages");
09720       if (!cmd) {
09721          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09722          cmd = ast_play_and_wait(chan, vms->fn);
09723       }
09724    }
09725    return cmd;
09726 }

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_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 (!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 4192 of file app_voicemail_imapstorage.c.

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

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

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

Definition at line 10662 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.

10663 {
10664    int res = 0;
10665    char *tmp;
10666    struct leave_vm_options leave_options;
10667    struct ast_flags flags = { 0 };
10668    char *opts[OPT_ARG_ARRAY_SIZE];
10669    AST_DECLARE_APP_ARGS(args,
10670       AST_APP_ARG(argv0);
10671       AST_APP_ARG(argv1);
10672    );
10673    
10674    memset(&leave_options, 0, sizeof(leave_options));
10675 
10676    if (chan->_state != AST_STATE_UP)
10677       ast_answer(chan);
10678 
10679    if (!ast_strlen_zero(data)) {
10680       tmp = ast_strdupa(data);
10681       AST_STANDARD_APP_ARGS(args, tmp);
10682       if (args.argc == 2) {
10683          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10684             return -1;
10685          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10686          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10687             int gain;
10688 
10689             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10690                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10691                return -1;
10692             } else {
10693                leave_options.record_gain = (signed char) gain;
10694             }
10695          }
10696          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10697             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10698                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10699          }
10700       }
10701    } else {
10702       char temp[256];
10703       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10704       if (res < 0)
10705          return res;
10706       if (ast_strlen_zero(temp))
10707          return 0;
10708       args.argv0 = ast_strdupa(temp);
10709    }
10710 
10711    res = leave_voicemail(chan, args.argv0, &leave_options);
10712    if (res == 't') {
10713       ast_play_and_wait(chan, "vm-goodbye");
10714       res = 0;
10715    }
10716 
10717    if (res == OPERATOR_EXIT) {
10718       res = 0;
10719    }
10720 
10721    if (res == ERROR_LOCK_PATH) {
10722       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10723       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10724       res = 0;
10725    }
10726 
10727    return res;
10728 }

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

Definition at line 9910 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_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), 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.

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

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 6870 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_STATUS_FILEINVALID, copy(), INTRO, make_file(), ast_vm_user::maxsecs, maxsilence, play_record_review(), silencethreshold, vm_pls_try_again, and vm_prepend_timeout.

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

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

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

09226 {
09227    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09228       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09229    } else {             /* Default to ENGLISH */
09230       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09231    }
09232 }

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

References ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_test_flag, ast_waitfordigit(), vm_state::curmsg, vm_state::deleted, vm_state::lastmsg, vm_state::newmessages, vm_state::repeats, vm_state::starting, vm_state::urgentmessages, VM_MESSAGEWRAP, vm_play_folder_name(), and vm_state::vmbox.

09114 {
09115    int res = 0;
09116    /* Play instructions and wait for new command */
09117    while (!res) {
09118       if (vms->starting) {
09119          if (vms->lastmsg > -1) {
09120             if (skipadvanced)
09121                res = ast_play_and_wait(chan, "vm-onefor-full");
09122             else
09123                res = ast_play_and_wait(chan, "vm-onefor");
09124             if (!res)
09125                res = vm_play_folder_name(chan, vms->vmbox);
09126          }
09127          if (!res) {
09128             if (skipadvanced)
09129                res = ast_play_and_wait(chan, "vm-opts-full");
09130             else
09131                res = ast_play_and_wait(chan, "vm-opts");
09132          }
09133       } else {
09134          /* Added for additional help */
09135          if (skipadvanced) {
09136             res = ast_play_and_wait(chan, "vm-onefor-full");
09137             if (!res)
09138                res = vm_play_folder_name(chan, vms->vmbox);
09139             res = ast_play_and_wait(chan, "vm-opts-full");
09140          }
09141          /* Logic:
09142           * If the current message is not the first OR
09143           * if we're listening to the first new message and there are
09144           * also urgent messages, then prompt for navigation to the
09145           * previous message
09146           */
09147          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
09148             res = ast_play_and_wait(chan, "vm-prev");
09149          }
09150          if (!res && !skipadvanced)
09151             res = ast_play_and_wait(chan, "vm-advopts");
09152          if (!res)
09153             res = ast_play_and_wait(chan, "vm-repeat");
09154          /* Logic:
09155           * If we're not listening to the last message OR
09156           * we're listening to the last urgent message and there are
09157           * also new non-urgent messages, then prompt for navigation
09158           * to the next message
09159           */
09160          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
09161             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
09162             res = ast_play_and_wait(chan, "vm-next");
09163          }
09164          if (!res) {
09165             int curmsg_deleted;
09166 #ifdef IMAP_STORAGE
09167             ast_mutex_lock(&vms->lock);
09168 #endif
09169             curmsg_deleted = vms->deleted[vms->curmsg];
09170 #ifdef IMAP_STORAGE
09171             ast_mutex_unlock(&vms->lock);
09172 #endif
09173             if (!curmsg_deleted) {
09174                res = ast_play_and_wait(chan, "vm-delete");
09175             } else {
09176                res = ast_play_and_wait(chan, "vm-undelete");
09177             }
09178             if (!res) {
09179                res = ast_play_and_wait(chan, "vm-toforward");
09180             }
09181             if (!res) {
09182                res = ast_play_and_wait(chan, "vm-savemessage");
09183             }
09184          }
09185       }
09186       if (!res) {
09187          res = ast_play_and_wait(chan, "vm-helpexit");
09188       }
09189       if (!res)
09190          res = ast_waitfordigit(chan, 6000);
09191       if (!res) {
09192          vms->repeats++;
09193          if (vms->repeats > 2) {
09194             res = 't';
09195          }
09196       }
09197    }
09198    return res;
09199 }

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

09202 {
09203    int res = 0;
09204    /* Play instructions and wait for new command */
09205    while (!res) {
09206       if (vms->lastmsg > -1) {
09207          res = ast_play_and_wait(chan, "vm-listen");
09208          if (!res)
09209             res = vm_play_folder_name(chan, vms->vmbox);
09210          if (!res)
09211             res = ast_play_and_wait(chan, "press");
09212          if (!res)
09213             res = ast_play_and_wait(chan, "digits/1");
09214       }
09215       if (!res)
09216          res = ast_play_and_wait(chan, "vm-opts");
09217       if (!res) {
09218          vms->starting = 0;
09219          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09220       }
09221    }
09222    return res;
09223 }

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

Definition at line 9051 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.

09052 {
09053    char prefile[256];
09054    
09055    /* Notify the user that the temp greeting is set and give them the option to remove it */
09056    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09057    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
09058       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09059       if (ast_fileexists(prefile, NULL, NULL) > 0) {
09060          ast_play_and_wait(chan, "vm-tempgreetactive");
09061       }
09062       DISPOSE(prefile, -1);
09063    }
09064 
09065    /* Play voicemail intro - syntax is different for different languages */
09066    if (0) {
09067       return 0;
09068    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
09069       return vm_intro_cs(chan, vms);
09070    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
09071       static int deprecation_warning = 0;
09072       if (deprecation_warning++ % 10 == 0) {
09073          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
09074       }
09075       return vm_intro_cs(chan, vms);
09076    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
09077       return vm_intro_de(chan, vms);
09078    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
09079       return vm_intro_es(chan, vms);
09080    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
09081       return vm_intro_fr(chan, vms);
09082    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
09083       return vm_intro_gr(chan, vms);
09084    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
09085       return vm_intro_he(chan, vms);
09086    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
09087       return vm_intro_it(chan, vms);
09088    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
09089       return vm_intro_nl(chan, vms);
09090    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
09091       return vm_intro_no(chan, vms);
09092    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
09093       return vm_intro_pl(chan, vms);
09094    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
09095       return vm_intro_pt_BR(chan, vms);
09096    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
09097       return vm_intro_pt(chan, vms);
09098    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
09099       return vm_intro_multilang(chan, vms, "n");
09100    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
09101       return vm_intro_se(chan, vms);
09102    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
09103       return vm_intro_multilang(chan, vms, "n");
09104    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
09105       return vm_intro_vi(chan, vms);
09106    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09107       return vm_intro_zh(chan, vms);
09108    } else {                                             /* Default to ENGLISH */
09109       return vm_intro_en(chan, vms);
09110    }
09111 }

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

Definition at line 8921 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.

08922 {
08923    int res;
08924    res = ast_play_and_wait(chan, "vm-youhave");
08925    if (!res) {
08926       if (vms->newmessages) {
08927          if (vms->newmessages == 1) {
08928             res = ast_play_and_wait(chan, "digits/jednu");
08929          } else {
08930             res = say_and_wait(chan, vms->newmessages, chan->language);
08931          }
08932          if (!res) {
08933             if ((vms->newmessages == 1))
08934                res = ast_play_and_wait(chan, "vm-novou");
08935             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08936                res = ast_play_and_wait(chan, "vm-nove");
08937             if (vms->newmessages > 4)
08938                res = ast_play_and_wait(chan, "vm-novych");
08939          }
08940          if (vms->oldmessages && !res)
08941             res = ast_play_and_wait(chan, "vm-and");
08942          else if (!res) {
08943             if ((vms->newmessages == 1))
08944                res = ast_play_and_wait(chan, "vm-zpravu");
08945             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08946                res = ast_play_and_wait(chan, "vm-zpravy");
08947             if (vms->newmessages > 4)
08948                res = ast_play_and_wait(chan, "vm-zprav");
08949          }
08950       }
08951       if (!res && vms->oldmessages) {
08952          res = say_and_wait(chan, vms->oldmessages, chan->language);
08953          if (!res) {
08954             if ((vms->oldmessages == 1))
08955                res = ast_play_and_wait(chan, "vm-starou");
08956             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08957                res = ast_play_and_wait(chan, "vm-stare");
08958             if (vms->oldmessages > 4)
08959                res = ast_play_and_wait(chan, "vm-starych");
08960          }
08961          if (!res) {
08962             if ((vms->oldmessages == 1))
08963                res = ast_play_and_wait(chan, "vm-zpravu");
08964             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08965                res = ast_play_and_wait(chan, "vm-zpravy");
08966             if (vms->oldmessages > 4)
08967                res = ast_play_and_wait(chan, "vm-zprav");
08968          }
08969       }
08970       if (!res) {
08971          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08972             res = ast_play_and_wait(chan, "vm-no");
08973             if (!res)
08974                res = ast_play_and_wait(chan, "vm-zpravy");
08975          }
08976       }
08977    }
08978    return res;
08979 }

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

Definition at line 8617 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.

08618 {
08619    /* Introduce messages they have */
08620    int res;
08621    res = ast_play_and_wait(chan, "vm-youhave");
08622    if (!res) {
08623       if (vms->newmessages) {
08624          if ((vms->newmessages == 1))
08625             res = ast_play_and_wait(chan, "digits/1F");
08626          else
08627             res = say_and_wait(chan, vms->newmessages, chan->language);
08628          if (!res)
08629             res = ast_play_and_wait(chan, "vm-INBOX");
08630          if (vms->oldmessages && !res)
08631             res = ast_play_and_wait(chan, "vm-and");
08632          else if (!res) {
08633             if ((vms->newmessages == 1))
08634                res = ast_play_and_wait(chan, "vm-message");
08635             else
08636                res = ast_play_and_wait(chan, "vm-messages");
08637          }
08638             
08639       }
08640       if (!res && vms->oldmessages) {
08641          if (vms->oldmessages == 1)
08642             res = ast_play_and_wait(chan, "digits/1F");
08643          else
08644             res = say_and_wait(chan, vms->oldmessages, chan->language);
08645          if (!res)
08646             res = ast_play_and_wait(chan, "vm-Old");
08647          if (!res) {
08648             if (vms->oldmessages == 1)
08649                res = ast_play_and_wait(chan, "vm-message");
08650             else
08651                res = ast_play_and_wait(chan, "vm-messages");
08652          }
08653       }
08654       if (!res) {
08655          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08656             res = ast_play_and_wait(chan, "vm-no");
08657             if (!res)
08658                res = ast_play_and_wait(chan, "vm-messages");
08659          }
08660       }
08661    }
08662    return res;
08663 }

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

Definition at line 8366 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.

08367 {
08368    int res;
08369 
08370    /* Introduce messages they have */
08371    res = ast_play_and_wait(chan, "vm-youhave");
08372    if (!res) {
08373       if (vms->urgentmessages) {
08374          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08375          if (!res)
08376             res = ast_play_and_wait(chan, "vm-Urgent");
08377          if ((vms->oldmessages || vms->newmessages) && !res) {
08378             res = ast_play_and_wait(chan, "vm-and");
08379          } else if (!res) {
08380             if ((vms->urgentmessages == 1))
08381                res = ast_play_and_wait(chan, "vm-message");
08382             else
08383                res = ast_play_and_wait(chan, "vm-messages");
08384          }
08385       }
08386       if (vms->newmessages) {
08387          res = say_and_wait(chan, vms->newmessages, chan->language);
08388          if (!res)
08389             res = ast_play_and_wait(chan, "vm-INBOX");
08390          if (vms->oldmessages && !res)
08391             res = ast_play_and_wait(chan, "vm-and");
08392          else if (!res) {
08393             if ((vms->newmessages == 1))
08394                res = ast_play_and_wait(chan, "vm-message");
08395             else
08396                res = ast_play_and_wait(chan, "vm-messages");
08397          }
08398             
08399       }
08400       if (!res && vms->oldmessages) {
08401          res = say_and_wait(chan, vms->oldmessages, chan->language);
08402          if (!res)
08403             res = ast_play_and_wait(chan, "vm-Old");
08404          if (!res) {
08405             if (vms->oldmessages == 1)
08406                res = ast_play_and_wait(chan, "vm-message");
08407             else
08408                res = ast_play_and_wait(chan, "vm-messages");
08409          }
08410       }
08411       if (!res) {
08412          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08413             res = ast_play_and_wait(chan, "vm-no");
08414             if (!res)
08415                res = ast_play_and_wait(chan, "vm-messages");
08416          }
08417       }
08418    }
08419    return res;
08420 }

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

Definition at line 8666 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.

08667 {
08668    /* Introduce messages they have */
08669    int res;
08670    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08671       res = ast_play_and_wait(chan, "vm-youhaveno");
08672       if (!res)
08673          res = ast_play_and_wait(chan, "vm-messages");
08674    } else {
08675       res = ast_play_and_wait(chan, "vm-youhave");
08676    }
08677    if (!res) {
08678       if (vms->newmessages) {
08679          if (!res) {
08680             if ((vms->newmessages == 1)) {
08681                res = ast_play_and_wait(chan, "digits/1M");
08682                if (!res)
08683                   res = ast_play_and_wait(chan, "vm-message");
08684                if (!res)
08685                   res = ast_play_and_wait(chan, "vm-INBOXs");
08686             } else {
08687                res = say_and_wait(chan, vms->newmessages, chan->language);
08688                if (!res)
08689                   res = ast_play_and_wait(chan, "vm-messages");
08690                if (!res)
08691                   res = ast_play_and_wait(chan, "vm-INBOX");
08692             }
08693          }
08694          if (vms->oldmessages && !res)
08695             res = ast_play_and_wait(chan, "vm-and");
08696       }
08697       if (vms->oldmessages) {
08698          if (!res) {
08699             if (vms->oldmessages == 1) {
08700                res = ast_play_and_wait(chan, "digits/1M");
08701                if (!res)
08702                   res = ast_play_and_wait(chan, "vm-message");
08703                if (!res)
08704                   res = ast_play_and_wait(chan, "vm-Olds");
08705             } else {
08706                res = say_and_wait(chan, vms->oldmessages, chan->language);
08707                if (!res)
08708                   res = ast_play_and_wait(chan, "vm-messages");
08709                if (!res)
08710                   res = ast_play_and_wait(chan, "vm-Old");
08711             }
08712          }
08713       }
08714    }
08715 return res;
08716 }

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

Definition at line 8764 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.

08765 {
08766    /* Introduce messages they have */
08767    int res;
08768    res = ast_play_and_wait(chan, "vm-youhave");
08769    if (!res) {
08770       if (vms->newmessages) {
08771          res = say_and_wait(chan, vms->newmessages, chan->language);
08772          if (!res)
08773             res = ast_play_and_wait(chan, "vm-INBOX");
08774          if (vms->oldmessages && !res)
08775             res = ast_play_and_wait(chan, "vm-and");
08776          else if (!res) {
08777             if ((vms->newmessages == 1))
08778                res = ast_play_and_wait(chan, "vm-message");
08779             else
08780                res = ast_play_and_wait(chan, "vm-messages");
08781          }
08782             
08783       }
08784       if (!res && vms->oldmessages) {
08785          res = say_and_wait(chan, vms->oldmessages, chan->language);
08786          if (!res)
08787             res = ast_play_and_wait(chan, "vm-Old");
08788          if (!res) {
08789             if (vms->oldmessages == 1)
08790                res = ast_play_and_wait(chan, "vm-message");
08791             else
08792                res = ast_play_and_wait(chan, "vm-messages");
08793          }
08794       }
08795       if (!res) {
08796          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08797             res = ast_play_and_wait(chan, "vm-no");
08798             if (!res)
08799                res = ast_play_and_wait(chan, "vm-messages");
08800          }
08801       }
08802    }
08803    return res;
08804 }

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

Definition at line 8165 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.

08166 {
08167    int res = 0;
08168 
08169    if (vms->newmessages) {
08170       res = ast_play_and_wait(chan, "vm-youhave");
08171       if (!res) 
08172          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
08173       if (!res) {
08174          if ((vms->newmessages == 1)) {
08175             res = ast_play_and_wait(chan, "vm-INBOX");
08176             if (!res)
08177                res = ast_play_and_wait(chan, "vm-message");
08178          } else {
08179             res = ast_play_and_wait(chan, "vm-INBOXs");
08180             if (!res)
08181                res = ast_play_and_wait(chan, "vm-messages");
08182          }
08183       }
08184    } else if (vms->oldmessages){
08185       res = ast_play_and_wait(chan, "vm-youhave");
08186       if (!res)
08187          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
08188       if ((vms->oldmessages == 1)){
08189          res = ast_play_and_wait(chan, "vm-Old");
08190          if (!res)
08191             res = ast_play_and_wait(chan, "vm-message");
08192       } else {
08193          res = ast_play_and_wait(chan, "vm-Olds");
08194          if (!res)
08195             res = ast_play_and_wait(chan, "vm-messages");
08196       }
08197    } else if (!vms->oldmessages && !vms->newmessages) 
08198       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
08199    return res;
08200 }

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

Definition at line 8299 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.

08300 {
08301    int res = 0;
08302 
08303    /* Introduce messages they have */
08304    if (!res) {
08305       if ((vms->newmessages) || (vms->oldmessages)) {
08306          res = ast_play_and_wait(chan, "vm-youhave");
08307       }
08308       /*
08309        * The word "shtei" refers to the number 2 in hebrew when performing a count
08310        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08311        * an element, this is one of them.
08312        */
08313       if (vms->newmessages) {
08314          if (!res) {
08315             if (vms->newmessages == 1) {
08316                res = ast_play_and_wait(chan, "vm-INBOX1");
08317             } else {
08318                if (vms->newmessages == 2) {
08319                   res = ast_play_and_wait(chan, "vm-shtei");
08320                } else {
08321                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08322                }
08323                res = ast_play_and_wait(chan, "vm-INBOX");
08324             }
08325          }
08326          if (vms->oldmessages && !res) {
08327             res = ast_play_and_wait(chan, "vm-and");
08328             if (vms->oldmessages == 1) {
08329                res = ast_play_and_wait(chan, "vm-Old1");
08330             } else {
08331                if (vms->oldmessages == 2) {
08332                   res = ast_play_and_wait(chan, "vm-shtei");
08333                } else {
08334                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08335                }
08336                res = ast_play_and_wait(chan, "vm-Old");
08337             }
08338          }
08339       }
08340       if (!res && vms->oldmessages && !vms->newmessages) {
08341          if (!res) {
08342             if (vms->oldmessages == 1) {
08343                res = ast_play_and_wait(chan, "vm-Old1");
08344             } else {
08345                if (vms->oldmessages == 2) {
08346                   res = ast_play_and_wait(chan, "vm-shtei");
08347                } else {
08348                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08349                }
08350                res = ast_play_and_wait(chan, "vm-Old");
08351             }
08352          }
08353       }
08354       if (!res) {
08355          if (!vms->oldmessages && !vms->newmessages) {
08356             if (!res) {
08357                res = ast_play_and_wait(chan, "vm-nomessages");
08358             }
08359          }
08360       }
08361    }
08362    return res;
08363 }

static int vm_intro_it ( 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, say_and_wait(), and vm_state::urgentmessages.

08424 {
08425    /* Introduce messages they have */
08426    int res;
08427    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08428       res = ast_play_and_wait(chan, "vm-no") ||
08429          ast_play_and_wait(chan, "vm-message");
08430    else
08431       res = ast_play_and_wait(chan, "vm-youhave");
08432    if (!res && vms->newmessages) {
08433       res = (vms->newmessages == 1) ?
08434          ast_play_and_wait(chan, "digits/un") ||
08435          ast_play_and_wait(chan, "vm-nuovo") ||
08436          ast_play_and_wait(chan, "vm-message") :
08437          /* 2 or more new messages */
08438          say_and_wait(chan, vms->newmessages, chan->language) ||
08439          ast_play_and_wait(chan, "vm-nuovi") ||
08440          ast_play_and_wait(chan, "vm-messages");
08441       if (!res && vms->oldmessages)
08442          res = ast_play_and_wait(chan, "vm-and");
08443    }
08444    if (!res && vms->oldmessages) {
08445       res = (vms->oldmessages == 1) ?
08446          ast_play_and_wait(chan, "digits/un") ||
08447          ast_play_and_wait(chan, "vm-vecchio") ||
08448          ast_play_and_wait(chan, "vm-message") :
08449          /* 2 or more old messages */
08450          say_and_wait(chan, vms->oldmessages, chan->language) ||
08451          ast_play_and_wait(chan, "vm-vecchi") ||
08452          ast_play_and_wait(chan, "vm-messages");
08453    }
08454    return res;
08455 }

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

Definition at line 8259 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.

08260 {
08261    int res;
08262    int lastnum = 0;
08263 
08264    res = ast_play_and_wait(chan, "vm-youhave");
08265 
08266    if (!res && vms->newmessages) {
08267       lastnum = vms->newmessages;
08268 
08269       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08270          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08271       }
08272 
08273       if (!res && vms->oldmessages) {
08274          res = ast_play_and_wait(chan, "vm-and");
08275       }
08276    }
08277 
08278    if (!res && vms->oldmessages) {
08279       lastnum = vms->oldmessages;
08280 
08281       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08282          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08283       }
08284    }
08285 
08286    if (!res) {
08287       if (lastnum == 0) {
08288          res = ast_play_and_wait(chan, "vm-no");
08289       }
08290       if (!res) {
08291          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08292       }
08293    }
08294 
08295    return res;
08296 }

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

Definition at line 8807 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.

08808 {
08809    /* Introduce messages they have */
08810    int res;
08811    res = ast_play_and_wait(chan, "vm-youhave");
08812    if (!res) {
08813       if (vms->newmessages) {
08814          res = say_and_wait(chan, vms->newmessages, chan->language);
08815          if (!res) {
08816             if (vms->newmessages == 1)
08817                res = ast_play_and_wait(chan, "vm-INBOXs");
08818             else
08819                res = ast_play_and_wait(chan, "vm-INBOX");
08820          }
08821          if (vms->oldmessages && !res)
08822             res = ast_play_and_wait(chan, "vm-and");
08823          else if (!res) {
08824             if ((vms->newmessages == 1))
08825                res = ast_play_and_wait(chan, "vm-message");
08826             else
08827                res = ast_play_and_wait(chan, "vm-messages");
08828          }
08829             
08830       }
08831       if (!res && vms->oldmessages) {
08832          res = say_and_wait(chan, vms->oldmessages, chan->language);
08833          if (!res) {
08834             if (vms->oldmessages == 1)
08835                res = ast_play_and_wait(chan, "vm-Olds");
08836             else
08837                res = ast_play_and_wait(chan, "vm-Old");
08838          }
08839          if (!res) {
08840             if (vms->oldmessages == 1)
08841                res = ast_play_and_wait(chan, "vm-message");
08842             else
08843                res = ast_play_and_wait(chan, "vm-messages");
08844          }
08845       }
08846       if (!res) {
08847          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08848             res = ast_play_and_wait(chan, "vm-no");
08849             if (!res)
08850                res = ast_play_and_wait(chan, "vm-messages");
08851          }
08852       }
08853    }
08854    return res;
08855 }

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

Definition at line 8573 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.

08574 {
08575    /* Introduce messages they have */
08576    int res;
08577 
08578    res = ast_play_and_wait(chan, "vm-youhave");
08579    if (res)
08580       return res;
08581 
08582    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08583       res = ast_play_and_wait(chan, "vm-no");
08584       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08585       return res;
08586    }
08587 
08588    if (vms->newmessages) {
08589       if ((vms->newmessages == 1)) {
08590          res = ast_play_and_wait(chan, "digits/1");
08591          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08592          res = res ? res : ast_play_and_wait(chan, "vm-message");
08593       } else {
08594          res = say_and_wait(chan, vms->newmessages, chan->language);
08595          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08596          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08597       }
08598       if (!res && vms->oldmessages)
08599          res = ast_play_and_wait(chan, "vm-and");
08600    }
08601    if (!res && vms->oldmessages) {
08602       if (vms->oldmessages == 1) {
08603          res = ast_play_and_wait(chan, "digits/1");
08604          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08605          res = res ? res : ast_play_and_wait(chan, "vm-message");
08606       } else {
08607          res = say_and_wait(chan, vms->oldmessages, chan->language);
08608          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08609          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08610       }
08611    }
08612 
08613    return res;
08614 }

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

Definition at line 8458 of file app_voicemail_imapstorage.c.

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

08459 {
08460    /* Introduce messages they have */
08461    int res;
08462    div_t num;
08463 
08464    if (!vms->oldmessages && !vms->newmessages) {
08465       res = ast_play_and_wait(chan, "vm-no");
08466       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08467       return res;
08468    } else {
08469       res = ast_play_and_wait(chan, "vm-youhave");
08470    }
08471 
08472    if (vms->newmessages) {
08473       num = div(vms->newmessages, 10);
08474       if (vms->newmessages == 1) {
08475          res = ast_play_and_wait(chan, "digits/1-a");
08476          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08477          res = res ? res : ast_play_and_wait(chan, "vm-message");
08478       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08479          if (num.rem == 2) {
08480             if (!num.quot) {
08481                res = ast_play_and_wait(chan, "digits/2-ie");
08482             } else {
08483                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08484                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08485             }
08486          } else {
08487             res = say_and_wait(chan, vms->newmessages, chan->language);
08488          }
08489          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08490          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08491       } else {
08492          res = say_and_wait(chan, vms->newmessages, chan->language);
08493          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08494          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08495       }
08496       if (!res && vms->oldmessages)
08497          res = ast_play_and_wait(chan, "vm-and");
08498    }
08499    if (!res && vms->oldmessages) {
08500       num = div(vms->oldmessages, 10);
08501       if (vms->oldmessages == 1) {
08502          res = ast_play_and_wait(chan, "digits/1-a");
08503          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08504          res = res ? res : ast_play_and_wait(chan, "vm-message");
08505       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08506          if (num.rem == 2) {
08507             if (!num.quot) {
08508                res = ast_play_and_wait(chan, "digits/2-ie");
08509             } else {
08510                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08511                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08512             }
08513          } else {
08514             res = say_and_wait(chan, vms->oldmessages, chan->language);
08515          }
08516          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08517          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08518       } else {
08519          res = say_and_wait(chan, vms->oldmessages, chan->language);
08520          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08521          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08522       }
08523    }
08524 
08525    return res;
08526 }

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

Definition at line 8858 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.

08859 {
08860    /* Introduce messages they have */
08861    int res;
08862    res = ast_play_and_wait(chan, "vm-youhave");
08863    if (!res) {
08864       if (vms->newmessages) {
08865          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08866          if (!res) {
08867             if ((vms->newmessages == 1)) {
08868                res = ast_play_and_wait(chan, "vm-message");
08869                if (!res)
08870                   res = ast_play_and_wait(chan, "vm-INBOXs");
08871             } else {
08872                res = ast_play_and_wait(chan, "vm-messages");
08873                if (!res)
08874                   res = ast_play_and_wait(chan, "vm-INBOX");
08875             }
08876          }
08877          if (vms->oldmessages && !res)
08878             res = ast_play_and_wait(chan, "vm-and");
08879       }
08880       if (!res && vms->oldmessages) {
08881          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08882          if (!res) {
08883             if (vms->oldmessages == 1) {
08884                res = ast_play_and_wait(chan, "vm-message");
08885                if (!res)
08886                   res = ast_play_and_wait(chan, "vm-Olds");
08887             } else {
08888                res = ast_play_and_wait(chan, "vm-messages");
08889                if (!res)
08890                   res = ast_play_and_wait(chan, "vm-Old");
08891             }
08892          }
08893       }
08894       if (!res) {
08895          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08896             res = ast_play_and_wait(chan, "vm-no");
08897             if (!res)
08898                res = ast_play_and_wait(chan, "vm-messages");
08899          }
08900       }
08901    }
08902    return res;
08903 }

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

Definition at line 8719 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.

08719                                                                           {
08720    /* Introduce messages they have */
08721    int res;
08722    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08723       res = ast_play_and_wait(chan, "vm-nomessages");
08724       return res;
08725    } else {
08726       res = ast_play_and_wait(chan, "vm-youhave");
08727    }
08728    if (vms->newmessages) {
08729       if (!res)
08730          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08731       if ((vms->newmessages == 1)) {
08732          if (!res)
08733             res = ast_play_and_wait(chan, "vm-message");
08734          if (!res)
08735             res = ast_play_and_wait(chan, "vm-INBOXs");
08736       } else {
08737          if (!res)
08738             res = ast_play_and_wait(chan, "vm-messages");
08739          if (!res)
08740             res = ast_play_and_wait(chan, "vm-INBOX");
08741       }
08742       if (vms->oldmessages && !res)
08743          res = ast_play_and_wait(chan, "vm-and");
08744    }
08745    if (vms->oldmessages) {
08746       if (!res)
08747          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08748       if (vms->oldmessages == 1) {
08749          if (!res)
08750             res = ast_play_and_wait(chan, "vm-message");
08751          if (!res)
08752             res = ast_play_and_wait(chan, "vm-Olds");
08753       } else {
08754          if (!res)
08755             res = ast_play_and_wait(chan, "vm-messages");
08756          if (!res)
08757             res = ast_play_and_wait(chan, "vm-Old");
08758       }
08759    }
08760    return res;
08761 }

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

Definition at line 8529 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.

08530 {
08531    /* Introduce messages they have */
08532    int res;
08533 
08534    res = ast_play_and_wait(chan, "vm-youhave");
08535    if (res)
08536       return res;
08537 
08538    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08539       res = ast_play_and_wait(chan, "vm-no");
08540       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08541       return res;
08542    }
08543 
08544    if (vms->newmessages) {
08545       if ((vms->newmessages == 1)) {
08546          res = ast_play_and_wait(chan, "digits/ett");
08547          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08548          res = res ? res : ast_play_and_wait(chan, "vm-message");
08549       } else {
08550          res = say_and_wait(chan, vms->newmessages, chan->language);
08551          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08552          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08553       }
08554       if (!res && vms->oldmessages)
08555          res = ast_play_and_wait(chan, "vm-and");
08556    }
08557    if (!res && vms->oldmessages) {
08558       if (vms->oldmessages == 1) {
08559          res = ast_play_and_wait(chan, "digits/ett");
08560          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08561          res = res ? res : ast_play_and_wait(chan, "vm-message");
08562       } else {
08563          res = say_and_wait(chan, vms->oldmessages, chan->language);
08564          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08565          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08566       }
08567    }
08568 
08569    return res;
08570 }

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

Definition at line 9021 of file app_voicemail_imapstorage.c.

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

09022 {
09023    int res;
09024 
09025    /* Introduce messages they have */
09026    res = ast_play_and_wait(chan, "vm-youhave");
09027    if (!res) {
09028       if (vms->newmessages) {
09029          res = say_and_wait(chan, vms->newmessages, chan->language);
09030          if (!res)
09031             res = ast_play_and_wait(chan, "vm-INBOX");
09032          if (vms->oldmessages && !res)
09033             res = ast_play_and_wait(chan, "vm-and");
09034       }
09035       if (!res && vms->oldmessages) {
09036          res = say_and_wait(chan, vms->oldmessages, chan->language);
09037          if (!res)
09038             res = ast_play_and_wait(chan, "vm-Old");        
09039       }
09040       if (!res) {
09041          if (!vms->oldmessages && !vms->newmessages) {
09042             res = ast_play_and_wait(chan, "vm-no");
09043             if (!res)
09044                res = ast_play_and_wait(chan, "vm-message");
09045          }
09046       }
09047    }
09048    return res;
09049 }

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

Definition at line 8982 of file app_voicemail_imapstorage.c.

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

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

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03268 {
03269    switch (ast_lock_path(path)) {
03270    case AST_LOCK_TIMEOUT:
03271       return -1;
03272    default:
03273       return 0;
03274    }
03275 }

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

09236 {
09237    int cmd = 0;
09238    int duration = 0;
09239    int tries = 0;
09240    char newpassword[80] = "";
09241    char newpassword2[80] = "";
09242    char prefile[PATH_MAX] = "";
09243    unsigned char buf[256];
09244    int bytes = 0;
09245 
09246    ast_test_suite_event_notify("NEWUSER", "Message: entering new user state");
09247    if (ast_adsi_available(chan)) {
09248       bytes += adsi_logo(buf + bytes);
09249       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09250       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09251       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09252       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09253       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09254    }
09255 
09256    /* If forcename is set, have the user record their name */
09257    if (ast_test_flag(vmu, VM_FORCENAME)) {
09258       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09259       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09260          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09261          if (cmd < 0 || cmd == 't' || cmd == '#')
09262             return cmd;
09263       }
09264    }
09265 
09266    /* If forcegreetings is set, have the user record their greetings */
09267    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09268       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09269       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09270          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09271          if (cmd < 0 || cmd == 't' || cmd == '#')
09272             return cmd;
09273       }
09274 
09275       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09276       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09277          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09278          if (cmd < 0 || cmd == 't' || cmd == '#')
09279             return cmd;
09280       }
09281    }
09282 
09283    /*
09284     * Change the password last since new users will be able to skip over any steps this one comes before
09285     * by hanging up and calling back to voicemail main since the password is used to verify new user status.
09286     */
09287    for (;;) {
09288       newpassword[1] = '\0';
09289       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09290       if (cmd == '#')
09291          newpassword[0] = '\0';
09292       if (cmd < 0 || cmd == 't' || cmd == '#')
09293          return cmd;
09294       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09295       if (cmd < 0 || cmd == 't' || cmd == '#')
09296          return cmd;
09297       cmd = check_password(vmu, newpassword); /* perform password validation */
09298       if (cmd != 0) {
09299          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09300          cmd = ast_play_and_wait(chan, vm_invalid_password);
09301       } else {
09302          newpassword2[1] = '\0';
09303          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09304          if (cmd == '#')
09305             newpassword2[0] = '\0';
09306          if (cmd < 0 || cmd == 't' || cmd == '#')
09307             return cmd;
09308          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09309          if (cmd < 0 || cmd == 't' || cmd == '#')
09310             return cmd;
09311          if (!strcmp(newpassword, newpassword2))
09312             break;
09313          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09314          cmd = ast_play_and_wait(chan, vm_mismatch);
09315       }
09316       if (++tries == 3)
09317          return -1;
09318       if (cmd != 0) {
09319          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09320       }
09321    }
09322    if (pwdchange & PWDCHANGE_INTERNAL)
09323       vm_change_password(vmu, newpassword);
09324    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09325       vm_change_password_shell(vmu, newpassword);
09326 
09327    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09328    cmd = ast_play_and_wait(chan, vm_passchanged);
09329 
09330    return cmd;
09331 }

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

09334 {
09335    int cmd = 0;
09336    int retries = 0;
09337    int duration = 0;
09338    char newpassword[80] = "";
09339    char newpassword2[80] = "";
09340    char prefile[PATH_MAX] = "";
09341    unsigned char buf[256];
09342    int bytes = 0;
09343 
09344    ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options");
09345    if (ast_adsi_available(chan)) {
09346       bytes += adsi_logo(buf + bytes);
09347       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09348       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09349       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09350       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09351       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09352    }
09353    while ((cmd >= 0) && (cmd != 't')) {
09354       if (cmd)
09355          retries = 0;
09356       switch (cmd) {
09357       case '1': /* Record your unavailable message */
09358          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09359          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09360          break;
09361       case '2':  /* Record your busy message */
09362          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09363          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09364          break;
09365       case '3': /* Record greeting */
09366          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09367          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09368          break;
09369       case '4':  /* manage the temporary greeting */
09370          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09371          break;
09372       case '5': /* change password */
09373          if (vmu->password[0] == '-') {
09374             cmd = ast_play_and_wait(chan, "vm-no");
09375             break;
09376          }
09377          newpassword[1] = '\0';
09378          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09379          if (cmd == '#')
09380             newpassword[0] = '\0';
09381          else {
09382             if (cmd < 0)
09383                break;
09384             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09385                break;
09386             }
09387          }
09388          cmd = check_password(vmu, newpassword); /* perform password validation */
09389          if (cmd != 0) {
09390             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09391             cmd = ast_play_and_wait(chan, vm_invalid_password);
09392             if (!cmd) {
09393                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09394             }
09395             break;
09396          }
09397          newpassword2[1] = '\0';
09398          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09399          if (cmd == '#')
09400             newpassword2[0] = '\0';
09401          else {
09402             if (cmd < 0)
09403                break;
09404 
09405             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09406                break;
09407             }
09408          }
09409          if (strcmp(newpassword, newpassword2)) {
09410             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09411             cmd = ast_play_and_wait(chan, vm_mismatch);
09412             if (!cmd) {
09413                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09414             }
09415             break;
09416          }
09417 
09418          if (pwdchange & PWDCHANGE_INTERNAL) {
09419             vm_change_password(vmu, newpassword);
09420          }
09421          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) {
09422             vm_change_password_shell(vmu, newpassword);
09423          }
09424 
09425          ast_debug(1, "User %s set password to %s of length %d\n",
09426             vms->username, newpassword, (int) strlen(newpassword));
09427          cmd = ast_play_and_wait(chan, vm_passchanged);
09428          break;
09429       case '*': 
09430          cmd = 't';
09431          break;
09432       default: 
09433          cmd = 0;
09434          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09435          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09436          if (ast_fileexists(prefile, NULL, NULL)) {
09437             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09438          }
09439          DISPOSE(prefile, -1);
09440          if (!cmd) {
09441             cmd = ast_play_and_wait(chan, "vm-options");
09442          }
09443          if (!cmd) {
09444             cmd = ast_waitfordigit(chan, 6000);
09445          }
09446          if (!cmd) {
09447             retries++;
09448          }
09449          if (retries > 3) {
09450             cmd = 't';
09451          }
09452          ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09453       }
09454    }
09455    if (cmd == 't')
09456       cmd = 0;
09457    return cmd;
09458 }

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

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

08129 {
08130    int cmd;
08131 
08132    if (  !strncasecmp(chan->language, "it", 2) ||
08133         !strncasecmp(chan->language, "es", 2) ||
08134         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
08135       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
08136       return cmd ? cmd : ast_play_and_wait(chan, box);
08137    } else if (!strncasecmp(chan->language, "gr", 2)) {
08138       return vm_play_folder_name_gr(chan, box);
08139    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
08140       return ast_play_and_wait(chan, box);
08141    } else if (!strncasecmp(chan->language, "pl", 2)) {
08142       return vm_play_folder_name_pl(chan, box);
08143    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
08144       return vm_play_folder_name_ua(chan, box);
08145    } else if (!strncasecmp(chan->language, "vi", 2)) {
08146       return ast_play_and_wait(chan, box);
08147    } else {  /* Default English */
08148       cmd = ast_play_and_wait(chan, box);
08149       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
08150    }
08151 }

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

Definition at line 8081 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

08082 {
08083    int cmd;
08084    char *buf;
08085 
08086    buf = alloca(strlen(box) + 2);
08087    strcpy(buf, box);
08088    strcat(buf, "s");
08089 
08090    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
08091       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
08092       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08093    } else {
08094       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
08095       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
08096    }
08097 }

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

Definition at line 8099 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

08100 {
08101    int cmd;
08102 
08103    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
08104       if (!strcasecmp(box, "vm-INBOX"))
08105          cmd = ast_play_and_wait(chan, "vm-new-e");
08106       else
08107          cmd = ast_play_and_wait(chan, "vm-old-e");
08108       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08109    } else {
08110       cmd = ast_play_and_wait(chan, "vm-messages");
08111       return cmd ? cmd : ast_play_and_wait(chan, box);
08112    }
08113 }

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

Definition at line 8115 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

08116 {
08117    int cmd;
08118 
08119    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
08120       cmd = ast_play_and_wait(chan, "vm-messages");
08121       return cmd ? cmd : ast_play_and_wait(chan, box);
08122    } else {
08123       cmd = ast_play_and_wait(chan, box);
08124       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
08125    }
08126 }

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

09477 {
09478    int cmd = 0;
09479    int retries = 0;
09480    int duration = 0;
09481    char prefile[PATH_MAX] = "";
09482    unsigned char buf[256];
09483    int bytes = 0;
09484 
09485    if (ast_adsi_available(chan)) {
09486       bytes += adsi_logo(buf + bytes);
09487       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09488       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09489       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09490       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09491       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09492    }
09493 
09494    ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options");
09495    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09496    while ((cmd >= 0) && (cmd != 't')) {
09497       if (cmd)
09498          retries = 0;
09499       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09500       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09501          cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09502          if (cmd == -1) {
09503             break;
09504          }
09505          cmd = 't';  
09506       } else {
09507          switch (cmd) {
09508          case '1':
09509             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
09510             break;
09511          case '2':
09512             DELETE(prefile, -1, prefile, vmu);
09513             ast_play_and_wait(chan, "vm-tempremoved");
09514             cmd = 't';  
09515             break;
09516          case '*': 
09517             cmd = 't';
09518             break;
09519          default:
09520             cmd = ast_play_and_wait(chan,
09521                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09522                   "vm-tempgreeting2" : "vm-tempgreeting");
09523             if (!cmd) {
09524                cmd = ast_waitfordigit(chan, 6000);
09525             }
09526             if (!cmd) {
09527                retries++;
09528             }
09529             if (retries > 3) {
09530                cmd = 't';
09531             }
09532             ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", cmd, cmd);
09533          }
09534       }
09535       DISPOSE(prefile, -1);
09536    }
09537    if (cmd == 't')
09538       cmd = 0;
09539    return cmd;
09540 }

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

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

11432 {
11433    struct ast_vm_user *user;
11434 
11435    AST_LIST_LOCK(&users);
11436    AST_LIST_TRAVERSE(&users, user, list) {
11437       vm_users_data_provider_get_helper(search, data_root, user);
11438    }
11439    AST_LIST_UNLOCK(&users);
11440 
11441    return 0;
11442 }

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

11385 {
11386    struct ast_data *data_user, *data_zone;
11387    struct ast_data *data_state;
11388    struct vm_zone *zone = NULL;
11389    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11390    char ext_context[256] = "";
11391 
11392    data_user = ast_data_add_node(data_root, "user");
11393    if (!data_user) {
11394       return -1;
11395    }
11396 
11397    ast_data_add_structure(ast_vm_user, data_user, user);
11398 
11399    AST_LIST_LOCK(&zones);
11400    AST_LIST_TRAVERSE(&zones, zone, list) {
11401       if (!strcmp(zone->name, user->zonetag)) {
11402          break;
11403       }
11404    }
11405    AST_LIST_UNLOCK(&zones);
11406 
11407    /* state */
11408    data_state = ast_data_add_node(data_user, "state");
11409    if (!data_state) {
11410       return -1;
11411    }
11412    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11413    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11414    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11415    ast_data_add_int(data_state, "newmsg", newmsg);
11416    ast_data_add_int(data_state, "oldmsg", oldmsg);
11417 
11418    if (zone) {
11419       data_zone = ast_data_add_node(data_user, "zone");
11420       ast_data_add_structure(vm_zone, data_zone, zone);
11421    }
11422 
11423    if (!ast_data_search_match(search, data_user)) {
11424       ast_data_remove_node(data_root, data_user);
11425    }
11426 
11427    return 0;
11428 }

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

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

11068 {
11069    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
11070    struct ast_vm_user vmus;
11071    char *options = NULL;
11072    int silent = 0, skipuser = 0;
11073    int res = -1;
11074    
11075    if (data) {
11076       s = ast_strdupa(data);
11077       user = strsep(&s, ",");
11078       options = strsep(&s, ",");
11079       if (user) {
11080          s = user;
11081          user = strsep(&s, "@");
11082          context = strsep(&s, "");
11083          if (!ast_strlen_zero(user))
11084             skipuser++;
11085          ast_copy_string(mailbox, user, sizeof(mailbox));
11086       }
11087    }
11088 
11089    if (options) {
11090       silent = (strchr(options, 's')) != NULL;
11091    }
11092 
11093    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11094       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
11095       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
11096       ast_play_and_wait(chan, "auth-thankyou");
11097       res = 0;
11098    } else if (mailbox[0] == '*') {
11099       /* user entered '*' */
11100       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
11101          res = 0; /* prevent hangup */
11102       }
11103    }
11104 
11105    return res;
11106 }

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

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

12610 {
12611    char *context;
12612    char *args_copy;
12613    int res;
12614 
12615    if (ast_strlen_zero(data)) {
12616       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context\n");
12617       return -1;
12618    }
12619 
12620    args_copy = ast_strdupa(data);
12621    if ((context = strchr(args_copy, '@'))) {
12622       *context++ = '\0';
12623    } else {
12624       context = "default";
12625    }
12626 
12627    if ((res = sayname(chan, args_copy, context) < 0)) {
12628       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12629       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12630       if (!res) {
12631          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12632       }
12633    }
12634 
12635    return res;
12636 }

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

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

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

Definition at line 7477 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 7469 of file app_voicemail_imapstorage.c.

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

07470 {
07471    int res;
07472    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07473       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07474    return res;
07475 }

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

Definition at line 12576 of file app_voicemail_imapstorage.c.

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

12576                                                                               {
12577    struct ast_config *conf;
12578    struct ast_category *cat;
12579    struct ast_variable *var;
12580    int res = -1;
12581 
12582    if (!(conf = ast_config_new())) {
12583       ast_log(LOG_ERROR, "Error creating new config structure\n");
12584       return res;
12585    }
12586    if (!(cat = ast_category_new("general", "", 1))) {
12587       ast_log(LOG_ERROR, "Error creating new category structure\n");
12588       ast_config_destroy(conf);
12589       return res;
12590    }
12591    if (!(var = ast_variable_new("password", password, ""))) {
12592       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12593       ast_config_destroy(conf);
12594       ast_category_destroy(cat);
12595       return res;
12596    }
12597    ast_category_append(conf, cat);
12598    ast_variable_append(cat, var);
12599    if (!ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12600       res = 0;
12601    } else {
12602       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12603    }
12604 
12605    ast_config_destroy(conf);
12606    return res;
12607 }


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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .nonoptreq = "res_adsi,res_smdi", } [static]

Definition at line 13688 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 13688 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 11306 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 11062 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 11449 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 11444 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 Mon Oct 8 12:39:10 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7