Mon Jun 27 16:51:01 2011

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 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, 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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_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 404 of file app_voicemail_imapstorage.c.

#define BASELINELEN   72

Definition at line 427 of file app_voicemail_imapstorage.c.

#define BASEMAXINLINE   256

Definition at line 428 of file app_voicemail_imapstorage.c.

#define CHUNKSIZE   65536

Definition at line 401 of file app_voicemail_imapstorage.c.

#define COMMAND_TIMEOUT   5000

Definition at line 397 of file app_voicemail_imapstorage.c.

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

Definition at line 711 of file app_voicemail_imapstorage.c.

#define DATA_EXPORT_VM_USERS ( USER   ) 

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

#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY   "#"

Definition at line 409 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY   "0"

Definition at line 411 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_RESTART_KEY   "2"

Definition at line 412 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY   "*"

Definition at line 410 of file app_voicemail_imapstorage.c.

#define DEFAULT_LISTEN_CONTROL_STOP_KEY   "13456789"

Definition at line 413 of file app_voicemail_imapstorage.c.

#define DEFAULT_POLL_FREQ   30

By default, poll every 30 seconds

Definition at line 781 of file app_voicemail_imapstorage.c.

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

Definition at line 712 of file app_voicemail_imapstorage.c.

#define DISPOSE ( a,
 ) 

Definition at line 707 of file app_voicemail_imapstorage.c.

#define ENDL   "\n"

Definition at line 432 of file app_voicemail_imapstorage.c.

#define ERROR_LOCK_PATH   -100

Definition at line 457 of file app_voicemail_imapstorage.c.

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

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

#define MAX_DATETIME_FORMAT   512

Definition at line 435 of file app_voicemail_imapstorage.c.

#define MAX_NUM_CID_CONTEXTS   10

Definition at line 436 of file app_voicemail_imapstorage.c.

#define MAXMSG   100

Definition at line 422 of file app_voicemail_imapstorage.c.

#define MAXMSGLIMIT   9999

Definition at line 423 of file app_voicemail_imapstorage.c.

#define MINPASSWORD   0

Default minimum mailbox password length

Definition at line 425 of file app_voicemail_imapstorage.c.

#define OPERATOR_EXIT   300

Definition at line 458 of file app_voicemail_imapstorage.c.

#define PWDCHANGE_EXTERNAL   (1 << 2)

Definition at line 724 of file app_voicemail_imapstorage.c.

#define PWDCHANGE_INTERNAL   (1 << 1)

Definition at line 723 of file app_voicemail_imapstorage.c.

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

Definition at line 710 of file app_voicemail_imapstorage.c.

#define RETRIEVE ( a,
b,
c,
 ) 

Definition at line 706 of file app_voicemail_imapstorage.c.

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

Definition at line 418 of file app_voicemail_imapstorage.c.

#define SMDI_MWI_WAIT_TIMEOUT   1000

Definition at line 395 of file app_voicemail_imapstorage.c.

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

Definition at line 708 of file app_voicemail_imapstorage.c.

#define tdesc   "Comedian Mail (Voicemail System)"

Definition at line 733 of file app_voicemail_imapstorage.c.

#define VALID_DTMF   "1234567890*#"

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

#define VM_ATTACH   (1 << 11)

Attach message to voicemail notifications?

Definition at line 449 of file app_voicemail_imapstorage.c.

#define VM_DELETE   (1 << 12)

Delete message after sending notification

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

#define VM_ENVELOPE   (1 << 4)

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

Definition at line 442 of file app_voicemail_imapstorage.c.

#define VM_FORCEGREET   (1 << 8)

Have new users record their greetings

Definition at line 446 of file app_voicemail_imapstorage.c.

#define VM_FORCENAME   (1 << 7)

Have new users record their name

Definition at line 445 of file app_voicemail_imapstorage.c.

#define VM_FWDURGAUTO   (1 << 18)

Autoset of Urgent flag on forwarded Urgent messages set globally

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

#define VM_MOVEHEARD   (1 << 16)

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

Definition at line 454 of file app_voicemail_imapstorage.c.

#define VM_OPERATOR   (1 << 1)

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

Definition at line 439 of file app_voicemail_imapstorage.c.

#define VM_PBXSKIP   (1 << 9)

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

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

#define VM_SAYCID   (1 << 2)

Repeat the CallerID info during envelope playback

Definition at line 440 of file app_voicemail_imapstorage.c.

#define VM_SAYDURATION   (1 << 5)

Play the length of the message during envelope playback

Definition at line 443 of file app_voicemail_imapstorage.c.

#define VM_SEARCH   (1 << 14)

Search all contexts for a matching mailbox

Definition at line 452 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 444 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 441 of file app_voicemail_imapstorage.c.

#define VM_TEMPGREETWARN   (1 << 15)

Remind user tempgreeting is set

Definition at line 453 of file app_voicemail_imapstorage.c.

#define VMSTATE_MAX_MSG_ARRAY   256

Definition at line 648 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 403 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_DIR_MODE   0777

Definition at line 399 of file app_voicemail_imapstorage.c.

#define VOICEMAIL_FILE_MODE   0666

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

00461             {
00462    NEW_FOLDER,
00463    OLD_FOLDER,
00464    WORK_FOLDER,
00465    FAMILY_FOLDER,
00466    FRIENDS_FOLDER,
00467    GREETINGS_FOLDER
00468 };

enum vm_option_args

Enumerator:
OPT_ARG_RECORDGAIN 
OPT_ARG_PLAYFOLDER 
OPT_ARG_DTMFEXIT 
OPT_ARG_ARRAY_SIZE 

Definition at line 482 of file app_voicemail_imapstorage.c.

00482                     {
00483    OPT_ARG_RECORDGAIN = 0,
00484    OPT_ARG_PLAYFOLDER = 1,
00485    OPT_ARG_DTMFEXIT   = 2,
00486    /* This *must* be the last value in this enum! */
00487    OPT_ARG_ARRAY_SIZE = 3,
00488 };

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

00470                      {
00471    OPT_SILENT =           (1 << 0),
00472    OPT_BUSY_GREETING =    (1 << 1),
00473    OPT_UNAVAIL_GREETING = (1 << 2),
00474    OPT_RECORDGAIN =       (1 << 3),
00475    OPT_PREPEND_MAILBOX =  (1 << 4),
00476    OPT_AUTOPLAY =         (1 << 6),
00477    OPT_DTMFEXIT =         (1 << 7),
00478    OPT_MESSAGE_Urgent =   (1 << 8),
00479    OPT_MESSAGE_PRIORITY = (1 << 9)
00480 };

enum vm_passwordlocation

Enumerator:
OPT_PWLOC_VOICEMAILCONF 
OPT_PWLOC_SPOOLDIR 
OPT_PWLOC_USERSCONF 

Definition at line 490 of file app_voicemail_imapstorage.c.

00490                          {
00491    OPT_PWLOC_VOICEMAILCONF = 0,
00492    OPT_PWLOC_SPOOLDIR      = 1,
00493    OPT_PWLOC_USERSCONF     = 2,
00494 };


Function Documentation

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

Definition at line 5245 of file app_voicemail_imapstorage.c.

References ast_strlen_zero().

05246 {
05247    DIR *dir;
05248    struct dirent *de;
05249    char fn[256];
05250    int ret = 0;
05251 
05252    /* If no mailbox, return immediately */
05253    if (ast_strlen_zero(mailbox))
05254       return 0;
05255 
05256    if (ast_strlen_zero(folder))
05257       folder = "INBOX";
05258    if (ast_strlen_zero(context))
05259       context = "default";
05260 
05261    snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
05262 
05263    if (!(dir = opendir(fn)))
05264       return 0;
05265 
05266    while ((de = readdir(dir))) {
05267       if (!strncasecmp(de->d_name, "msg", 3)) {
05268          if (shortcircuit) {
05269             ret = 1;
05270             break;
05271          } else if (!strncasecmp(de->d_name + 8, "txt", 3)) {
05272             ret++;
05273          }
05274       }
05275    }
05276 
05277    closedir(dir);
05278 
05279    return ret;
05280 }

static void __reg_module ( void   )  [static]

Definition at line 13243 of file app_voicemail_imapstorage.c.

static void __unreg_module ( void   )  [static]

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

10745 {
10746    struct ast_vm_user svm;
10747    AST_DECLARE_APP_ARGS(arg,
10748       AST_APP_ARG(mbox);
10749       AST_APP_ARG(context);
10750    );
10751 
10752    AST_NONSTANDARD_APP_ARGS(arg, args, '@');
10753 
10754    if (ast_strlen_zero(arg.mbox)) {
10755       ast_log(LOG_ERROR, "MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
10756       return -1;
10757    }
10758 
10759    ast_copy_string(buf, find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox) ? "1" : "0", len);
10760    return 0;
10761 }

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 4663 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, VOICEMAIL_FILE_MODE, and ast_vm_user::volgain.

04664 {
04665    char tmpdir[256], newtmp[256];
04666    char fname[256];
04667    char tmpcmd[256];
04668    int tmpfd = -1;
04669 
04670    /* Eww. We want formats to tell us their own MIME type */
04671    char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
04672 
04673    if (vmu->volgain < -.001 || vmu->volgain > .001) {
04674       create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
04675       snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
04676       tmpfd = mkstemp(newtmp);
04677       chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
04678       ast_debug(3, "newtmp: %s\n", newtmp);
04679       if (tmpfd > -1) {
04680          int soxstatus;
04681          snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
04682          if ((soxstatus = ast_safe_system(tmpcmd)) == 0) {
04683             attach = newtmp;
04684             ast_debug(3, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
04685          } else {
04686             ast_log(LOG_WARNING, "Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
04687                soxstatus == 1 ? "Problem with command line options" : "An error occurred during file processing");
04688             ast_log(LOG_WARNING, "Voicemail attachment will have no volume gain.\n");
04689          }
04690       }
04691    }
04692    fprintf(p, "--%s" ENDL, bound);
04693    if (msgnum > -1)
04694       fprintf(p, "Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
04695    else
04696       fprintf(p, "Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
04697    fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
04698    fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
04699    if (msgnum > -1)
04700       fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
04701    else
04702       fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
04703    snprintf(fname, sizeof(fname), "%s.%s", attach, format);
04704    base_encode(fname, p);
04705    if (last)
04706       fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
04707    if (tmpfd > -1) {
04708       unlink(fname);
04709       close(tmpfd);
04710       unlink(newtmp);
04711    }
04712    return 0;
04713 }

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

Definition at line 6261 of file app_voicemail_imapstorage.c.

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

06262 {
06263    int x;
06264    if (!ast_adsi_available(chan))
06265       return;
06266    x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
06267    if (x < 0)
06268       return;
06269    if (!x) {
06270       if (adsi_load_vmail(chan, useadsi)) {
06271          ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n");
06272          return;
06273       }
06274    } else
06275       *useadsi = 1;
06276 }

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

Definition at line 6450 of file app_voicemail_imapstorage.c.

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

06451 {
06452    int bytes = 0;
06453    unsigned char buf[256];
06454    unsigned char keys[8];
06455 
06456    int x;
06457 
06458    if (!ast_adsi_available(chan))
06459       return;
06460 
06461    /* New meaning for keys */
06462    for (x = 0; x < 5; x++)
06463       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06464 
06465    keys[6] = 0x0;
06466    keys[7] = 0x0;
06467 
06468    if (!vms->curmsg) {
06469       /* No prev key, provide "Folder" instead */
06470       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06471    }
06472    if (vms->curmsg >= vms->lastmsg) {
06473       /* If last message ... */
06474       if (vms->curmsg) {
06475          /* but not only message, provide "Folder" instead */
06476          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06477       } else {
06478          /* Otherwise if only message, leave blank */
06479          keys[3] = 1;
06480       }
06481    }
06482 
06483    /* If deleted, show "undeleted" */
06484    if (vms->deleted[vms->curmsg]) 
06485       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06486 
06487    /* Except "Exit" */
06488    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06489    bytes += ast_adsi_set_keys(buf + bytes, keys);
06490    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06491 
06492    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06493 }

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

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

06327 {
06328    unsigned char buf[256];
06329    int bytes = 0;
06330    unsigned char keys[8];
06331    int x, y;
06332 
06333    if (!ast_adsi_available(chan))
06334       return;
06335 
06336    for (x = 0; x < 5; x++) {
06337       y = ADSI_KEY_APPS + 12 + start + x;
06338       if (y > ADSI_KEY_APPS + 12 + 4)
06339          y = 0;
06340       keys[x] = ADSI_KEY_SKT | y;
06341    }
06342    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
06343    keys[6] = 0;
06344    keys[7] = 0;
06345 
06346    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
06347    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
06348    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06349    bytes += ast_adsi_set_keys(buf + bytes, keys);
06350    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06351 
06352    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06353 }

static void adsi_goodbye ( struct ast_channel chan  )  [static]

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

06599 {
06600    unsigned char buf[256];
06601    int bytes = 0;
06602 
06603    if (!ast_adsi_available(chan))
06604       return;
06605    bytes += adsi_logo(buf + bytes);
06606    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
06607    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
06608    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06609    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06610 
06611    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06612 }

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

Definition at line 6132 of file app_voicemail_imapstorage.c.

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

06133 {
06134    unsigned char buf[256];
06135    int bytes = 0;
06136    int x;
06137    char num[5];
06138 
06139    *useadsi = 0;
06140    bytes += ast_adsi_data_mode(buf + bytes);
06141    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06142 
06143    bytes = 0;
06144    bytes += adsi_logo(buf);
06145    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06146 #ifdef DISPLAY
06147    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .", "");
06148 #endif
06149    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06150    bytes += ast_adsi_data_mode(buf + bytes);
06151    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06152 
06153    if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
06154       bytes = 0;
06155       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
06156       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06157       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06158       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06159       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06160       return 0;
06161    }
06162 
06163 #ifdef DISPLAY
06164    /* Add a dot */
06165    bytes = 0;
06166    bytes += ast_adsi_logo(buf);
06167    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
06168    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ..", "");
06169    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06170    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06171 #endif
06172    bytes = 0;
06173    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
06174    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
06175    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
06176    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
06177    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
06178    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
06179    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06180 
06181 #ifdef DISPLAY
06182    /* Add another dot */
06183    bytes = 0;
06184    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ...", "");
06185    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06186 
06187    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06188    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06189 #endif
06190 
06191    bytes = 0;
06192    /* These buttons we load but don't use yet */
06193    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
06194    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
06195    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
06196    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
06197    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
06198    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
06199    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06200 
06201 #ifdef DISPLAY
06202    /* Add another dot */
06203    bytes = 0;
06204    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   ....", "");
06205    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06206    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06207 #endif
06208 
06209    bytes = 0;
06210    for (x = 0; x < 5; x++) {
06211       snprintf(num, sizeof(num), "%d", x);
06212       bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(NULL, x), mbox(NULL, x), num, 1);
06213    }
06214    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
06215    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06216 
06217 #ifdef DISPLAY
06218    /* Add another dot */
06219    bytes = 0;
06220    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, "   .....", "");
06221    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06222    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06223 #endif
06224 
06225    if (ast_adsi_end_download(chan)) {
06226       bytes = 0;
06227       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
06228       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
06229       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06230       bytes += ast_adsi_voice_mode(buf + bytes, 0);
06231       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06232       return 0;
06233    }
06234    bytes = 0;
06235    bytes += ast_adsi_download_disconnect(buf + bytes);
06236    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06237    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
06238 
06239    ast_debug(1, "Done downloading scripts...\n");
06240 
06241 #ifdef DISPLAY
06242    /* Add last dot */
06243    bytes = 0;
06244    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "   ......", "");
06245    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06246 #endif
06247    ast_debug(1, "Restarting session...\n");
06248 
06249    bytes = 0;
06250    /* Load the session now */
06251    if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
06252       *useadsi = 1;
06253       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
06254    } else
06255       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
06256 
06257    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06258    return 0;
06259 }

static void adsi_login ( struct ast_channel chan  )  [static]

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

06279 {
06280    unsigned char buf[256];
06281    int bytes = 0;
06282    unsigned char keys[8];
06283    int x;
06284    if (!ast_adsi_available(chan))
06285       return;
06286 
06287    for (x = 0; x < 8; x++)
06288       keys[x] = 0;
06289    /* Set one key for next */
06290    keys[3] = ADSI_KEY_APPS + 3;
06291 
06292    bytes += adsi_logo(buf + bytes);
06293    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
06294    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
06295    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06296    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
06297    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
06298    bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
06299    bytes += ast_adsi_set_keys(buf + bytes, keys);
06300    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06301    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06302 }

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

Definition at line 6124 of file app_voicemail_imapstorage.c.

References ADSI_COMM_PAGE, ADSI_JUST_CENT, and ast_adsi_display().

06125 {
06126    int bytes = 0;
06127    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
06128    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
06129    return bytes;
06130 }

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

Definition at line 6355 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, and strsep().

06356 {
06357    int bytes = 0;
06358    unsigned char buf[256]; 
06359    char buf1[256], buf2[256];
06360    char fn2[PATH_MAX];
06361 
06362    char cid[256] = "";
06363    char *val;
06364    char *name, *num;
06365    char datetime[21] = "";
06366    FILE *f;
06367 
06368    unsigned char keys[8];
06369 
06370    int x;
06371 
06372    if (!ast_adsi_available(chan))
06373       return;
06374 
06375    /* Retrieve important info */
06376    snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
06377    f = fopen(fn2, "r");
06378    if (f) {
06379       while (!feof(f)) {   
06380          if (!fgets((char *) buf, sizeof(buf), f)) {
06381             continue;
06382          }
06383          if (!feof(f)) {
06384             char *stringp = NULL;
06385             stringp = (char *) buf;
06386             strsep(&stringp, "=");
06387             val = strsep(&stringp, "=");
06388             if (!ast_strlen_zero(val)) {
06389                if (!strcmp((char *) buf, "callerid"))
06390                   ast_copy_string(cid, val, sizeof(cid));
06391                if (!strcmp((char *) buf, "origdate"))
06392                   ast_copy_string(datetime, val, sizeof(datetime));
06393             }
06394          }
06395       }
06396       fclose(f);
06397    }
06398    /* New meaning for keys */
06399    for (x = 0; x < 5; x++)
06400       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
06401    keys[6] = 0x0;
06402    keys[7] = 0x0;
06403 
06404    if (!vms->curmsg) {
06405       /* No prev key, provide "Folder" instead */
06406       keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06407    }
06408    if (vms->curmsg >= vms->lastmsg) {
06409       /* If last message ... */
06410       if (vms->curmsg) {
06411          /* but not only message, provide "Folder" instead */
06412          keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
06413          bytes += ast_adsi_voice_mode(buf + bytes, 0);
06414 
06415       } else {
06416          /* Otherwise if only message, leave blank */
06417          keys[3] = 1;
06418       }
06419    }
06420 
06421    if (!ast_strlen_zero(cid)) {
06422       ast_callerid_parse(cid, &name, &num);
06423       if (!name)
06424          name = num;
06425    } else
06426       name = "Unknown Caller";
06427 
06428    /* If deleted, show "undeleted" */
06429 
06430    if (vms->deleted[vms->curmsg])
06431       keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
06432 
06433    /* Except "Exit" */
06434    keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
06435    snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
06436       strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
06437    snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
06438 
06439    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06440    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06441    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
06442    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
06443    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06444    bytes += ast_adsi_set_keys(buf + bytes, keys);
06445    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06446 
06447    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06448 }

static void adsi_password ( struct ast_channel chan  )  [static]

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

06305 {
06306    unsigned char buf[256];
06307    int bytes = 0;
06308    unsigned char keys[8];
06309    int x;
06310    if (!ast_adsi_available(chan))
06311       return;
06312 
06313    for (x = 0; x < 8; x++)
06314       keys[x] = 0;
06315    /* Set one key for next */
06316    keys[3] = ADSI_KEY_APPS + 3;
06317 
06318    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06319    bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
06320    bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
06321    bytes += ast_adsi_set_keys(buf + bytes, keys);
06322    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06323    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06324 }

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

Definition at line 6495 of file app_voicemail_imapstorage.c.

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

06496 {
06497    unsigned char buf[256] = "";
06498    char buf1[256] = "", buf2[256] = "";
06499    int bytes = 0;
06500    unsigned char keys[8];
06501    int x;
06502 
06503    char *newm = (vms->newmessages == 1) ? "message" : "messages";
06504    char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
06505    if (!ast_adsi_available(chan))
06506       return;
06507    if (vms->newmessages) {
06508       snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
06509       if (vms->oldmessages) {
06510          strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
06511          snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
06512       } else {
06513          snprintf(buf2, sizeof(buf2), "%s.", newm);
06514       }
06515    } else if (vms->oldmessages) {
06516       snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
06517       snprintf(buf2, sizeof(buf2), "%s.", oldm);
06518    } else {
06519       strcpy(buf1, "You have no messages.");
06520       buf2[0] = ' ';
06521       buf2[1] = '\0';
06522    }
06523    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06524    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06525    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06526 
06527    for (x = 0; x < 6; x++)
06528       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06529    keys[6] = 0;
06530    keys[7] = 0;
06531 
06532    /* Don't let them listen if there are none */
06533    if (vms->lastmsg < 0)
06534       keys[0] = 1;
06535    bytes += ast_adsi_set_keys(buf + bytes, keys);
06536 
06537    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06538 
06539    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06540 }

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

Definition at line 6542 of file app_voicemail_imapstorage.c.

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

06543 {
06544    unsigned char buf[256] = "";
06545    char buf1[256] = "", buf2[256] = "";
06546    int bytes = 0;
06547    unsigned char keys[8];
06548    int x;
06549 
06550    char *mess = (vms->lastmsg == 0) ? "message" : "messages";
06551 
06552    if (!ast_adsi_available(chan))
06553       return;
06554 
06555    /* Original command keys */
06556    for (x = 0; x < 6; x++)
06557       keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
06558 
06559    keys[6] = 0;
06560    keys[7] = 0;
06561 
06562    if ((vms->lastmsg + 1) < 1)
06563       keys[0] = 0;
06564 
06565    snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
06566       strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
06567 
06568    if (vms->lastmsg + 1)
06569       snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
06570    else
06571       strcpy(buf2, "no messages.");
06572    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
06573    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
06574    bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
06575    bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06576    bytes += ast_adsi_set_keys(buf + bytes, keys);
06577 
06578    bytes += ast_adsi_voice_mode(buf + bytes, 0);
06579 
06580    ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06581    
06582 }

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 12809 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_variable_retrieve(), ast_verb, ast_waitfordigit(), ast_vm_user::callback, CONFIG_FLAG_NOCACHE, config_flags, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, vm_state::curdir, vm_state::curmsg, ast_vm_user::dialout, dialout(), DISPOSE, find_user(), vm_state::fn, vm_state::heard, leave_voicemail(), ast_vm_user::mailbox, make_file(), play_message_callerid(), play_message_datetime(), RETRIEVE, vm_state::starting, and wait_file().

12810 {
12811    int res = 0;
12812    char filename[PATH_MAX];
12813    struct ast_config *msg_cfg = NULL;
12814    const char *origtime, *context;
12815    char *name, *num;
12816    int retries = 0;
12817    char *cid;
12818    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE, };
12819 
12820    vms->starting = 0; 
12821 
12822    make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
12823 
12824    /* Retrieve info from VM attribute file */
12825    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
12826    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
12827    msg_cfg = ast_config_load(filename, config_flags);
12828    DISPOSE(vms->curdir, vms->curmsg);
12829    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
12830       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
12831       return 0;
12832    }
12833 
12834    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
12835       ast_config_destroy(msg_cfg);
12836       return 0;
12837    }
12838 
12839    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
12840 
12841    context = ast_variable_retrieve(msg_cfg, "message", "context");
12842    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
12843       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
12844    switch (option) {
12845    case 3: /* Play message envelope */
12846       if (!res)
12847          res = play_message_datetime(chan, vmu, origtime, filename);
12848       if (!res)
12849          res = play_message_callerid(chan, vms, cid, context, 0);
12850 
12851       res = 't';
12852       break;
12853 
12854    case 2:  /* Call back */
12855 
12856       if (ast_strlen_zero(cid))
12857          break;
12858 
12859       ast_callerid_parse(cid, &name, &num);
12860       while ((res > -1) && (res != 't')) {
12861          switch (res) {
12862          case '1':
12863             if (num) {
12864                /* Dial the CID number */
12865                res = dialout(chan, vmu, num, vmu->callback);
12866                if (res) {
12867                   ast_config_destroy(msg_cfg);
12868                   return 9;
12869                }
12870             } else {
12871                res = '2';
12872             }
12873             break;
12874 
12875          case '2':
12876             /* Want to enter a different number, can only do this if there's a dialout context for this user */
12877             if (!ast_strlen_zero(vmu->dialout)) {
12878                res = dialout(chan, vmu, NULL, vmu->dialout);
12879                if (res) {
12880                   ast_config_destroy(msg_cfg);
12881                   return 9;
12882                }
12883             } else {
12884                ast_verb(3, "Caller can not specify callback number - no dialout context available\n");
12885                res = ast_play_and_wait(chan, "vm-sorry");
12886             }
12887             ast_config_destroy(msg_cfg);
12888             return res;
12889          case '*':
12890             res = 't';
12891             break;
12892          case '3':
12893          case '4':
12894          case '5':
12895          case '6':
12896          case '7':
12897          case '8':
12898          case '9':
12899          case '0':
12900 
12901             res = ast_play_and_wait(chan, "vm-sorry");
12902             retries++;
12903             break;
12904          default:
12905             if (num) {
12906                ast_verb(3, "Confirm CID number '%s' is number to use for callback\n", num);
12907                res = ast_play_and_wait(chan, "vm-num-i-have");
12908                if (!res)
12909                   res = play_message_callerid(chan, vms, num, vmu->context, 1);
12910                if (!res)
12911                   res = ast_play_and_wait(chan, "vm-tocallnum");
12912                /* Only prompt for a caller-specified number if there is a dialout context specified */
12913                if (!ast_strlen_zero(vmu->dialout)) {
12914                   if (!res)
12915                      res = ast_play_and_wait(chan, "vm-calldiffnum");
12916                }
12917             } else {
12918                res = ast_play_and_wait(chan, "vm-nonumber");
12919                if (!ast_strlen_zero(vmu->dialout)) {
12920                   if (!res)
12921                      res = ast_play_and_wait(chan, "vm-toenternumber");
12922                }
12923             }
12924             if (!res)
12925                res = ast_play_and_wait(chan, "vm-star-cancel");
12926             if (!res)
12927                res = ast_waitfordigit(chan, 6000);
12928             if (!res) {
12929                retries++;
12930                if (retries > 3)
12931                   res = 't';
12932             }
12933             break; 
12934             
12935          }
12936          if (res == 't')
12937             res = 0;
12938          else if (res == '*')
12939             res = -1;
12940       }
12941       break;
12942       
12943    case 1:  /* Reply */
12944       /* Send reply directly to sender */
12945       if (ast_strlen_zero(cid))
12946          break;
12947 
12948       ast_callerid_parse(cid, &name, &num);
12949       if (!num) {
12950          ast_verb(3, "No CID number available, no reply sent\n");
12951          if (!res)
12952             res = ast_play_and_wait(chan, "vm-nonumber");
12953          ast_config_destroy(msg_cfg);
12954          return res;
12955       } else {
12956          struct ast_vm_user vmu2;
12957          if (find_user(&vmu2, vmu->context, num)) {
12958             struct leave_vm_options leave_options;
12959             char mailbox[AST_MAX_EXTENSION * 2 + 2];
12960             snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
12961 
12962             ast_verb(3, "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
12963             
12964             memset(&leave_options, 0, sizeof(leave_options));
12965             leave_options.record_gain = record_gain;
12966             res = leave_voicemail(chan, mailbox, &leave_options);
12967             if (!res)
12968                res = 't';
12969             ast_config_destroy(msg_cfg);
12970             return res;
12971          } else {
12972             /* Sender has no mailbox, can't reply */
12973             ast_verb(3, "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
12974             ast_play_and_wait(chan, "vm-nobox");
12975             res = 't';
12976             ast_config_destroy(msg_cfg);
12977             return res;
12978          }
12979       } 
12980       res = 0;
12981 
12982       break;
12983    }
12984 
12985 #ifndef IMAP_STORAGE
12986    ast_config_destroy(msg_cfg);
12987 
12988    if (!res) {
12989       make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
12990       vms->heard[msg] = 1;
12991       res = wait_file(chan, vms, vms->fn);
12992    }
12993 #endif
12994    return res;
12995 }

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

Definition at line 10487 of file app_voicemail_imapstorage.c.

References apply_options(), ast_copy_string(), ast_strdupa, ast_vm_user::context, ast_vm_user::email, find_or_create(), ast_vm_user::fullname, inboxcount2(), 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(), and strsep().

10488 {
10489    /* Assumes lock is already held */
10490    char *tmp;
10491    char *stringp;
10492    char *s;
10493    struct ast_vm_user *vmu;
10494    char *mailbox_full;
10495    int new = 0, old = 0, urgent = 0;
10496    char secretfn[PATH_MAX] = "";
10497 
10498    tmp = ast_strdupa(data);
10499 
10500    if (!(vmu = find_or_create(context, box)))
10501       return -1;
10502 
10503    populate_defaults(vmu);
10504 
10505    stringp = tmp;
10506    if ((s = strsep(&stringp, ","))) {
10507       ast_copy_string(vmu->password, s, sizeof(vmu->password));
10508    }
10509    if (stringp && (s = strsep(&stringp, ","))) {
10510       ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
10511    }
10512    if (stringp && (s = strsep(&stringp, ","))) {
10513       ast_copy_string(vmu->email, s, sizeof(vmu->email));
10514    }
10515    if (stringp && (s = strsep(&stringp, ","))) {
10516       ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
10517    }
10518    if (stringp && (s = strsep(&stringp, ","))) {
10519       apply_options(vmu, s);
10520    }
10521 
10522    switch (vmu->passwordlocation) {
10523    case OPT_PWLOC_SPOOLDIR:
10524       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
10525       read_password_from_file(secretfn, vmu->password, sizeof(vmu->password));
10526    }
10527 
10528    mailbox_full = alloca(strlen(box) + strlen(context) + 1);
10529    strcpy(mailbox_full, box);
10530    strcat(mailbox_full, "@");
10531    strcat(mailbox_full, context);
10532 
10533    inboxcount2(mailbox_full, &urgent, &new, &old);
10534    queue_mwi_event(mailbox_full, urgent, new, old);
10535 
10536    return 0;
10537 }

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

References apply_options(), ast_copy_string(), ast_log(), AST_LOG_WARNING, ast_set2_flag, ast_true(), ast_vm_user::attachfmt, ast_vm_user::callback, ast_vm_user::dialout, 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, 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.

01010 {
01011    int x;
01012    if (!strcasecmp(var, "attach")) {
01013       ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
01014    } else if (!strcasecmp(var, "attachfmt")) {
01015       ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
01016    } else if (!strcasecmp(var, "serveremail")) {
01017       ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
01018    } else if (!strcasecmp(var, "language")) {
01019       ast_copy_string(vmu->language, value, sizeof(vmu->language));
01020    } else if (!strcasecmp(var, "tz")) {
01021       ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
01022    } else if (!strcasecmp(var, "locale")) {
01023       ast_copy_string(vmu->locale, value, sizeof(vmu->locale));
01024 #ifdef IMAP_STORAGE
01025    } else if (!strcasecmp(var, "imapuser")) {
01026       ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
01027       vmu->imapversion = imapversion;
01028    } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
01029       ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
01030       vmu->imapversion = imapversion;
01031    } else if (!strcasecmp(var, "imapfolder")) {
01032       ast_copy_string(vmu->imapfolder, value, sizeof(vmu->imapfolder));
01033    } else if (!strcasecmp(var, "imapvmshareid")) {
01034       ast_copy_string(vmu->imapvmshareid, value, sizeof(vmu->imapvmshareid));
01035       vmu->imapversion = imapversion;
01036 #endif
01037    } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
01038       ast_set2_flag(vmu, ast_true(value), VM_DELETE); 
01039    } else if (!strcasecmp(var, "saycid")){
01040       ast_set2_flag(vmu, ast_true(value), VM_SAYCID); 
01041    } else if (!strcasecmp(var, "sendvoicemail")){
01042       ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); 
01043    } else if (!strcasecmp(var, "review")){
01044       ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
01045    } else if (!strcasecmp(var, "tempgreetwarn")){
01046       ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);   
01047    } else if (!strcasecmp(var, "messagewrap")){
01048       ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP);  
01049    } else if (!strcasecmp(var, "operator")) {
01050       ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);  
01051    } else if (!strcasecmp(var, "envelope")){
01052       ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);  
01053    } else if (!strcasecmp(var, "moveheard")){
01054       ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD);
01055    } else if (!strcasecmp(var, "sayduration")){
01056       ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);  
01057    } else if (!strcasecmp(var, "saydurationm")){
01058       if (sscanf(value, "%30d", &x) == 1) {
01059          vmu->saydurationm = x;
01060       } else {
01061          ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
01062       }
01063    } else if (!strcasecmp(var, "forcename")){
01064       ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); 
01065    } else if (!strcasecmp(var, "forcegreetings")){
01066       ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);   
01067    } else if (!strcasecmp(var, "callback")) {
01068       ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
01069    } else if (!strcasecmp(var, "dialout")) {
01070       ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
01071    } else if (!strcasecmp(var, "exitcontext")) {
01072       ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
01073    } else if (!strcasecmp(var, "minsecs")) {
01074       if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
01075          vmu->minsecs = x;
01076       } else {
01077          ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
01078          vmu->minsecs = vmminsecs;
01079       }
01080    } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
01081       vmu->maxsecs = atoi(value);
01082       if (vmu->maxsecs <= 0) {
01083          ast_log(AST_LOG_WARNING, "Invalid max message length of %s. Using global value %d\n", value, vmmaxsecs);
01084          vmu->maxsecs = vmmaxsecs;
01085       } else {
01086          vmu->maxsecs = atoi(value);
01087       }
01088       if (!strcasecmp(var, "maxmessage"))
01089          ast_log(AST_LOG_WARNING, "Option 'maxmessage' has been deprecated in favor of 'maxsecs'.  Please make that change in your voicemail config.\n");
01090    } else if (!strcasecmp(var, "maxmsg")) {
01091       vmu->maxmsg = atoi(value);
01092       /* Accept maxmsg=0 (Greetings only voicemail) */
01093       if (vmu->maxmsg < 0) {
01094          ast_log(AST_LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %d\n", value, MAXMSG);
01095          vmu->maxmsg = MAXMSG;
01096       } else if (vmu->maxmsg > MAXMSGLIMIT) {
01097          ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
01098          vmu->maxmsg = MAXMSGLIMIT;
01099       }
01100    } else if (!strcasecmp(var, "nextaftercmd")) {
01101       ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
01102    } else if (!strcasecmp(var, "backupdeleted")) {
01103       if (sscanf(value, "%30d", &x) == 1)
01104          vmu->maxdeletedmsg = x;
01105       else if (ast_true(value))
01106          vmu->maxdeletedmsg = MAXMSG;
01107       else
01108          vmu->maxdeletedmsg = 0;
01109 
01110       if (vmu->maxdeletedmsg < 0) {
01111          ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value, MAXMSG);
01112          vmu->maxdeletedmsg = MAXMSG;
01113       } else if (vmu->maxdeletedmsg > MAXMSGLIMIT) {
01114          ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%s\n", MAXMSGLIMIT, value);
01115          vmu->maxdeletedmsg = MAXMSGLIMIT;
01116       }
01117    } else if (!strcasecmp(var, "volgain")) {
01118       sscanf(value, "%30lf", &vmu->volgain);
01119    } else if (!strcasecmp(var, "passwordlocation")) {
01120       if (!strcasecmp(value, "spooldir")) {
01121          vmu->passwordlocation = OPT_PWLOC_SPOOLDIR;
01122       } else {
01123          vmu->passwordlocation = OPT_PWLOC_VOICEMAILCONF;
01124       }
01125    } else if (!strcasecmp(var, "options")) {
01126       apply_options(vmu, value);
01127    }
01128 }

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

Destructively Parse options and apply.

Definition at line 1242 of file app_voicemail_imapstorage.c.

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

01243 {  
01244    char *stringp;
01245    char *s;
01246    char *var, *value;
01247    stringp = ast_strdupa(options);
01248    while ((s = strsep(&stringp, "|"))) {
01249       value = s;
01250       if ((var = strsep(&value, "=")) && value) {
01251          apply_option(vmu, var, value);
01252       }
01253    }  
01254 }

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

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

01262 {
01263    for (; var; var = var->next) {
01264       if (!strcasecmp(var->name, "vmsecret")) {
01265          ast_copy_string(retval->password, var->value, sizeof(retval->password));
01266       } else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) { /* don't overwrite vmsecret if it exists */
01267          if (ast_strlen_zero(retval->password))
01268             ast_copy_string(retval->password, var->value, sizeof(retval->password));
01269       } else if (!strcasecmp(var->name, "uniqueid")) {
01270          ast_copy_string(retval->uniqueid, var->value, sizeof(retval->uniqueid));
01271       } else if (!strcasecmp(var->name, "pager")) {
01272          ast_copy_string(retval->pager, var->value, sizeof(retval->pager));
01273       } else if (!strcasecmp(var->name, "email")) {
01274          ast_copy_string(retval->email, var->value, sizeof(retval->email));
01275       } else if (!strcasecmp(var->name, "fullname")) {
01276          ast_copy_string(retval->fullname, var->value, sizeof(retval->fullname));
01277       } else if (!strcasecmp(var->name, "context")) {
01278          ast_copy_string(retval->context, var->value, sizeof(retval->context));
01279       } else if (!strcasecmp(var->name, "emailsubject")) {
01280          retval->emailsubject = ast_strdup(var->value);
01281       } else if (!strcasecmp(var->name, "emailbody")) {
01282          retval->emailbody = ast_strdup(var->value);
01283 #ifdef IMAP_STORAGE
01284       } else if (!strcasecmp(var->name, "imapuser")) {
01285          ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
01286          retval->imapversion = imapversion;
01287       } else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
01288          ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
01289          retval->imapversion = imapversion;
01290       } else if (!strcasecmp(var->name, "imapfolder")) {
01291          ast_copy_string(retval->imapfolder, var->value, sizeof(retval->imapfolder));
01292       } else if (!strcasecmp(var->name, "imapvmshareid")) {
01293          ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
01294          retval->imapversion = imapversion;
01295 #endif
01296       } else
01297          apply_option(retval, var->name, var->value);
01298    }
01299 }

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

04339 {
04340    struct ast_str *tmp = ast_str_alloca(80);
04341    int first_section = 1;
04342 
04343    ast_str_reset(*end);
04344    ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04345    for (; *start; start++) {
04346       int need_encoding = 0;
04347       if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
04348          need_encoding = 1;
04349       }
04350       if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
04351          (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
04352          (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
04353          (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
04354          /* Start new line */
04355          ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
04356          ast_str_set(&tmp, -1, "=?%s?Q?", charset);
04357          first_section = 0;
04358       }
04359       if (need_encoding && *start == ' ') {
04360          ast_str_append(&tmp, -1, "_");
04361       } else if (need_encoding) {
04362          ast_str_append(&tmp, -1, "=%hhX", *start);
04363       } else {
04364          ast_str_append(&tmp, -1, "%c", *start);
04365       }
04366    }
04367    ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
04368    return ast_str_buffer(*end);
04369 }

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

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

04267 {
04268    const char *ptr;
04269 
04270    /* We're only ever passing 0 to maxlen, so short output isn't possible */
04271    ast_str_set(buf, maxlen, "\"");
04272    for (ptr = from; *ptr; ptr++) {
04273       if (*ptr == '"' || *ptr == '\\') {
04274          ast_str_append(buf, maxlen, "\\%c", *ptr);
04275       } else {
04276          ast_str_append(buf, maxlen, "%c", *ptr);
04277       }
04278    }
04279    ast_str_append(buf, maxlen, "\"");
04280 
04281    return ast_str_buffer(*buf);
04282 }

AST_TEST_DEFINE ( test_voicemail_vmuser   ) 

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

10540 {
10541    int res = 0;
10542    struct ast_vm_user *vmu;
10543    /* language parameter seems to only be used for display in manager action */
10544    static const char options_string[] = "attach=yes|attachfmt=wav49|"
10545       "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10546       "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10547       "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10548       "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10549       "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10550       "backupdeleted=50|volgain=1.3|passwordlocation=spooldir";
10551 #ifdef IMAP_STORAGE
10552    static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
10553       "imapfolder=INBOX|imapvmshareid=6000";
10554 #endif
10555 
10556    switch (cmd) {
10557    case TEST_INIT:
10558       info->name = "vmuser";
10559       info->category = "/apps/app_voicemail/";
10560       info->summary = "Vmuser unit test";
10561       info->description =
10562          "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10563       return AST_TEST_NOT_RUN;
10564    case TEST_EXECUTE:
10565       break;
10566    }
10567 
10568    if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
10569       return AST_TEST_NOT_RUN;
10570    }
10571    ast_set_flag(vmu, VM_ALLOCED);
10572 
10573    apply_options(vmu, options_string);
10574 
10575    if (!ast_test_flag(vmu, VM_ATTACH)) {
10576       ast_test_status_update(test, "Parse failure for attach option\n");
10577       res = 1;
10578    }
10579    if (strcasecmp(vmu->attachfmt, "wav49")) {
10580       ast_test_status_update(test, "Parse failure for attachftm option\n");
10581       res = 1;
10582    }
10583    if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
10584       ast_test_status_update(test, "Parse failure for serveremail option\n");
10585       res = 1;
10586    }
10587    if (strcasecmp(vmu->zonetag, "central")) {
10588       ast_test_status_update(test, "Parse failure for tz option\n");
10589       res = 1;
10590    }
10591    if (!ast_test_flag(vmu, VM_DELETE)) {
10592       ast_test_status_update(test, "Parse failure for delete option\n");
10593       res = 1;
10594    }
10595    if (!ast_test_flag(vmu, VM_SAYCID)) {
10596       ast_test_status_update(test, "Parse failure for saycid option\n");
10597       res = 1;
10598    }
10599    if (!ast_test_flag(vmu, VM_SVMAIL)) {
10600       ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
10601       res = 1;
10602    }
10603    if (!ast_test_flag(vmu, VM_REVIEW)) {
10604       ast_test_status_update(test, "Parse failure for review option\n");
10605       res = 1;
10606    }
10607    if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
10608       ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
10609       res = 1;
10610    }
10611    if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
10612       ast_test_status_update(test, "Parse failure for messagewrap option\n");
10613       res = 1;
10614    }
10615    if (!ast_test_flag(vmu, VM_OPERATOR)) {
10616       ast_test_status_update(test, "Parse failure for operator option\n");
10617       res = 1;
10618    }
10619    if (!ast_test_flag(vmu, VM_ENVELOPE)) {
10620       ast_test_status_update(test, "Parse failure for envelope option\n");
10621       res = 1;
10622    }
10623    if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
10624       ast_test_status_update(test, "Parse failure for moveheard option\n");
10625       res = 1;
10626    }
10627    if (!ast_test_flag(vmu, VM_SAYDURATION)) {
10628       ast_test_status_update(test, "Parse failure for sayduration option\n");
10629       res = 1;
10630    }
10631    if (vmu->saydurationm != 5) {
10632       ast_test_status_update(test, "Parse failure for saydurationm option\n");
10633       res = 1;
10634    }
10635    if (!ast_test_flag(vmu, VM_FORCENAME)) {
10636       ast_test_status_update(test, "Parse failure for forcename option\n");
10637       res = 1;
10638    }
10639    if (!ast_test_flag(vmu, VM_FORCEGREET)) {
10640       ast_test_status_update(test, "Parse failure for forcegreetings option\n");
10641       res = 1;
10642    }
10643    if (strcasecmp(vmu->callback, "somecontext")) {
10644       ast_test_status_update(test, "Parse failure for callbacks option\n");
10645       res = 1;
10646    }
10647    if (strcasecmp(vmu->dialout, "somecontext2")) {
10648       ast_test_status_update(test, "Parse failure for dialout option\n");
10649       res = 1;
10650    }
10651    if (strcasecmp(vmu->exit, "somecontext3")) {
10652       ast_test_status_update(test, "Parse failure for exitcontext option\n");
10653       res = 1;
10654    }
10655    if (vmu->minsecs != 10) {
10656       ast_test_status_update(test, "Parse failure for minsecs option\n");
10657       res = 1;
10658    }
10659    if (vmu->maxsecs != 100) {
10660       ast_test_status_update(test, "Parse failure for maxsecs option\n");
10661       res = 1;
10662    }
10663    if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10664       ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
10665       res = 1;
10666    }
10667    if (vmu->maxdeletedmsg != 50) {
10668       ast_test_status_update(test, "Parse failure for backupdeleted option\n");
10669       res = 1;
10670    }
10671    if (vmu->volgain != 1.3) {
10672       ast_test_status_update(test, "Parse failure for volgain option\n");
10673       res = 1;
10674    }
10675    if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
10676       ast_test_status_update(test, "Parse failure for passwordlocation option\n");
10677       res = 1;
10678    }
10679 #ifdef IMAP_STORAGE
10680    apply_options(vmu, option_string2);
10681 
10682    if (strcasecmp(vmu->imapuser, "imapuser")) {
10683       ast_test_status_update(test, "Parse failure for imapuser option\n");
10684       res = 1;
10685    }
10686    if (strcasecmp(vmu->imappassword, "imappasswd")) {
10687       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10688       res = 1;
10689    }
10690    if (strcasecmp(vmu->imapfolder, "INBOX")) {
10691       ast_test_status_update(test, "Parse failure for imappasswd option\n");
10692       res = 1;
10693    }
10694    if (strcasecmp(vmu->imapvmshareid, "6000")) {
10695       ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
10696       res = 1;
10697    }
10698 #endif
10699 
10700    free_user(vmu);
10701    return res ? AST_TEST_FAIL : AST_TEST_PASS;
10702 }

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

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

04143 {
04144    static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
04145       'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
04146       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
04147       '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
04148    int i, hiteof = 0;
04149    FILE *fi;
04150    struct baseio bio;
04151 
04152    memset(&bio, 0, sizeof(bio));
04153    bio.iocp = BASEMAXINLINE;
04154 
04155    if (!(fi = fopen(filename, "rb"))) {
04156       ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
04157       return -1;
04158    }
04159 
04160    while (!hiteof){
04161       unsigned char igroup[3], ogroup[4];
04162       int c, n;
04163 
04164       memset(igroup, 0, sizeof(igroup));
04165 
04166       for (n = 0; n < 3; n++) {
04167          if ((c = inchar(&bio, fi)) == EOF) {
04168             hiteof = 1;
04169             break;
04170          }
04171 
04172          igroup[n] = (unsigned char) c;
04173       }
04174 
04175       if (n > 0) {
04176          ogroup[0]= dtable[igroup[0] >> 2];
04177          ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
04178          ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
04179          ogroup[3]= dtable[igroup[2] & 0x3F];
04180 
04181          if (n < 3) {
04182             ogroup[3] = '=';
04183 
04184             if (n < 2)
04185                ogroup[2] = '=';
04186          }
04187 
04188          for (i = 0; i < 4; i++)
04189             ochar(&bio, ogroup[i], so);
04190       }
04191    }
04192 
04193    fclose(fi);
04194    
04195    if (fputs(ENDL, so) == EOF) {
04196       return 0;
04197    }
04198 
04199    return 1;
04200 }

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

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

01222 {
01223    int res = -1;
01224    if (!strcmp(vmu->password, password)) {
01225       /* No change (but an update would return 0 rows updated, so we opt out here) */
01226       return 0;
01227    }
01228 
01229    if (strlen(password) > 10) {
01230       ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL);
01231    }
01232    if (ast_update2_realtime("voicemail", "context", vmu->context, "mailbox", vmu->mailbox, SENTINEL, "password", password, SENTINEL) > 0) {
01233       ast_copy_string(vmu->password, password, sizeof(vmu->password));
01234       res = 0;
01235    }
01236    return res;
01237 }

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

04312 {
04313    for (; *str; str++) {
04314       if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
04315          return 1;
04316       }
04317    }
04318    return 0;
04319 }

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

01184 {
01185    /* check minimum length */
01186    if (strlen(password) < minpassword)
01187       return 1;
01188    if (!ast_strlen_zero(ext_pass_check_cmd)) {
01189       char cmd[255], buf[255];
01190 
01191       ast_log(AST_LOG_DEBUG, "Verify password policies for %s\n", password);
01192 
01193       snprintf(cmd, sizeof(cmd), "%s %s %s %s %s", ext_pass_check_cmd, vmu->mailbox, vmu->context, vmu->password, password);
01194       if (vm_check_password_shell(cmd, buf, sizeof(buf))) {
01195          ast_debug(5, "Result: %s\n", buf);
01196          if (!strncasecmp(buf, "VALID", 5)) {
01197             ast_debug(3, "Passed password check: '%s'\n", buf);
01198             return 0;
01199          } else if (!strncasecmp(buf, "FAILURE", 7)) {
01200             ast_log(AST_LOG_WARNING, "Unable to execute password validation script: '%s'.\n", buf);
01201             return 0;
01202          } else {
01203             ast_log(AST_LOG_NOTICE, "Password doesn't match policies for user %s %s\n", vmu->mailbox, password);
01204             return 1;
01205          }
01206       }
01207    }
01208    return 0;
01209 }

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

Definition at line 7765 of file app_voicemail_imapstorage.c.

References ast_check_realtime(), ast_log(), 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, vm_state::lastmsg, ast_vm_user::mailbox, make_file(), ast_vm_user::maxdeletedmsg, RENAME, save_to_folder(), vm_lock_path(), and VM_MOVEHEARD.

07766 {
07767    int x = 0;
07768 #ifndef IMAP_STORAGE
07769    int res = 0, nummsg;
07770    char fn2[PATH_MAX];
07771 #endif
07772 
07773    if (vms->lastmsg <= -1) {
07774       goto done;
07775    }
07776 
07777    vms->curmsg = -1;
07778 #ifndef IMAP_STORAGE
07779    /* Get the deleted messages fixed */
07780    if (vm_lock_path(vms->curdir)) {
07781       return ERROR_LOCK_PATH;
07782    }
07783 
07784    /* must check up to last detected message, just in case it is erroneously greater than maxmsg */
07785    for (x = 0; x < vms->lastmsg + 1; x++) {
07786       if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
07787          /* Save this message.  It's not in INBOX or hasn't been heard */
07788          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07789          if (!EXISTS(vms->curdir, x, vms->fn, NULL)) {
07790             break;
07791          }
07792          vms->curmsg++;
07793          make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg);
07794          if (strcmp(vms->fn, fn2)) {
07795             RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2);
07796          }
07797       } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
07798          /* Move to old folder before deleting */
07799          res = save_to_folder(vmu, vms, x, 1);
07800          if (res == ERROR_LOCK_PATH) {
07801             /* If save failed do not delete the message */
07802             ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
07803             vms->deleted[x] = 0;
07804             vms->heard[x] = 0;
07805             --x;
07806          }
07807       } else if (vms->deleted[x] && vmu->maxdeletedmsg) {
07808          /* Move to deleted folder */
07809          res = save_to_folder(vmu, vms, x, 10);
07810          if (res == ERROR_LOCK_PATH) {
07811             /* If save failed do not delete the message */
07812             vms->deleted[x] = 0;
07813             vms->heard[x] = 0;
07814             --x;
07815          }
07816       } else if (vms->deleted[x] && ast_check_realtime("voicemail_data")) {
07817          /* If realtime storage enabled - we should explicitly delete this message,
07818          cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */
07819          make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07820          if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07821             DELETE(vms->curdir, x, vms->fn, vmu);
07822          }
07823       }
07824    }
07825 
07826    /* Delete ALL remaining messages */
07827    nummsg = x - 1;
07828    for (x = vms->curmsg + 1; x <= nummsg; x++) {
07829       make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
07830       if (EXISTS(vms->curdir, x, vms->fn, NULL)) {
07831          DELETE(vms->curdir, x, vms->fn, vmu);
07832       }
07833    }
07834    ast_unlock_path(vms->curdir);
07835 #else /* defined(IMAP_STORAGE) */
07836    if (vms->deleted) {
07837       /* Since we now expunge after each delete, deleting in reverse order
07838        * ensures that no reordering occurs between each step. */
07839       for (x = vms->dh_arraysize - 1; x >= 0; x--) {
07840          if (vms->deleted[x]) {
07841             ast_debug(3, "IMAP delete of %d\n", x);
07842             DELETE(vms->curdir, x, vms->fn, vmu);
07843          }
07844       }
07845    }
07846 #endif
07847 
07848 done:
07849    if (vms->deleted && vmu->maxmsg) {
07850       memset(vms->deleted, 0, vms->dh_arraysize * sizeof(int));
07851    }
07852    if (vms->heard && vmu->maxmsg) {
07853       memset(vms->heard, 0, vms->dh_arraysize * sizeof(int));
07854    }
07855 
07856    return 0;
07857 }

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

Definition at line 10848 of file app_voicemail_imapstorage.c.

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

10849 {
10850    int which = 0;
10851    int wordlen;
10852    struct ast_vm_user *vmu;
10853    const char *context = "";
10854 
10855    /* 0 - show; 1 - voicemail; 2 - users; 3 - for; 4 - <context> */
10856    if (pos > 4)
10857       return NULL;
10858    if (pos == 3)
10859       return (state == 0) ? ast_strdup("for") : NULL;
10860    wordlen = strlen(word);
10861    AST_LIST_TRAVERSE(&users, vmu, list) {
10862       if (!strncasecmp(word, vmu->context, wordlen)) {
10863          if (context && strcmp(context, vmu->context) && ++which > state)
10864             return ast_strdup(vmu->context);
10865          /* ignore repeated contexts ? */
10866          context = vmu->context;
10867       }
10868    }
10869    return NULL;
10870 }

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

References ast_log(), errno, and VOICEMAIL_FILE_MODE.

03947 {
03948    int ifd;
03949    int ofd;
03950    int res;
03951    int len;
03952    char buf[4096];
03953 
03954 #ifdef HARDLINK_WHEN_POSSIBLE
03955    /* Hard link if possible; saves disk space & is faster */
03956    if (link(infile, outfile)) {
03957 #endif
03958       if ((ifd = open(infile, O_RDONLY)) < 0) {
03959          ast_log(AST_LOG_WARNING, "Unable to open %s in read-only mode: %s\n", infile, strerror(errno));
03960          return -1;
03961       }
03962       if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
03963          ast_log(AST_LOG_WARNING, "Unable to open %s in write-only mode: %s\n", outfile, strerror(errno));
03964          close(ifd);
03965          return -1;
03966       }
03967       do {
03968          len = read(ifd, buf, sizeof(buf));
03969          if (len < 0) {
03970             ast_log(AST_LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
03971             close(ifd);
03972             close(ofd);
03973             unlink(outfile);
03974          }
03975          if (len) {
03976             res = write(ofd, buf, len);
03977             if (errno == ENOMEM || errno == ENOSPC || res != len) {
03978                ast_log(AST_LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
03979                close(ifd);
03980                close(ofd);
03981                unlink(outfile);
03982             }
03983          }
03984       } while (len);
03985       close(ifd);
03986       close(ofd);
03987       return 0;
03988 #ifdef HARDLINK_WHEN_POSSIBLE
03989    } else {
03990       /* Hard link succeeded */
03991       return 0;
03992    }
03993 #endif
03994 }

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

05183 {
05184    char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
05185    const char *frombox = mbox(vmu, imbox);
05186    int recipmsgnum;
05187    int res = 0;
05188 
05189    ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
05190 
05191    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If urgent, copy to Urgent folder */
05192       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "Urgent");
05193    } else {
05194       create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
05195    }
05196    
05197    if (!dir)
05198       make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
05199    else
05200       ast_copy_string(fromdir, dir, sizeof(fromdir));
05201 
05202    make_file(frompath, sizeof(frompath), fromdir, msgnum);
05203    make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
05204 
05205    if (vm_lock_path(todir))
05206       return ERROR_LOCK_PATH;
05207 
05208    recipmsgnum = last_message_index(recip, todir) + 1;
05209    if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) {
05210       make_file(topath, sizeof(topath), todir, recipmsgnum);
05211 #ifndef ODBC_STORAGE
05212       if (EXISTS(fromdir, msgnum, frompath, chan->language)) { 
05213          COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
05214       } else {
05215 #endif
05216          /* If we are prepending a message for ODBC, then the message already
05217           * exists in the database, but we want to force copying from the
05218           * filesystem (since only the FS contains the prepend). */
05219          copy_plain_file(frompath, topath);
05220          STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
05221          vm_delete(topath);
05222 #ifndef ODBC_STORAGE
05223       }
05224 #endif
05225    } else {
05226       ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
05227       res = -1;
05228    }
05229    ast_unlock_path(todir);
05230    notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
05231       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05232       S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05233       flag);
05234    
05235    return res;
05236 }

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

04006 {
04007    char frompath2[PATH_MAX], topath2[PATH_MAX];
04008    struct ast_variable *tmp,*var = NULL;
04009    const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
04010    ast_filecopy(frompath, topath, NULL);
04011    snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
04012    snprintf(topath2, sizeof(topath2), "%s.txt", topath);
04013    if (ast_check_realtime("voicemail_data")) {
04014       var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
04015       /* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
04016       for (tmp = var; tmp; tmp = tmp->next) {
04017          if (!strcasecmp(tmp->name, "origmailbox")) {
04018             origmailbox = tmp->value;
04019          } else if (!strcasecmp(tmp->name, "context")) {
04020             context = tmp->value;
04021          } else if (!strcasecmp(tmp->name, "macrocontext")) {
04022             macrocontext = tmp->value;
04023          } else if (!strcasecmp(tmp->name, "exten")) {
04024             exten = tmp->value;
04025          } else if (!strcasecmp(tmp->name, "priority")) {
04026             priority = tmp->value;
04027          } else if (!strcasecmp(tmp->name, "callerchan")) {
04028             callerchan = tmp->value;
04029          } else if (!strcasecmp(tmp->name, "callerid")) {
04030             callerid = tmp->value;
04031          } else if (!strcasecmp(tmp->name, "origdate")) {
04032             origdate = tmp->value;
04033          } else if (!strcasecmp(tmp->name, "origtime")) {
04034             origtime = tmp->value;
04035          } else if (!strcasecmp(tmp->name, "category")) {
04036             category = tmp->value;
04037          } else if (!strcasecmp(tmp->name, "duration")) {
04038             duration = tmp->value;
04039          }
04040       }
04041       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);
04042    }
04043    copy(frompath2, topath2);
04044    ast_variables_destroy(var);
04045 }

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

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

03842 {
03843 
03844    int vmcount = 0;
03845    DIR *vmdir = NULL;
03846    struct dirent *vment = NULL;
03847 
03848    if (vm_lock_path(dir))
03849       return ERROR_LOCK_PATH;
03850 
03851    if ((vmdir = opendir(dir))) {
03852       while ((vment = readdir(vmdir))) {
03853          if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) {
03854             vmcount++;
03855          }
03856       }
03857       closedir(vmdir);
03858    }
03859    ast_unlock_path(dir);
03860    
03861    return vmcount;
03862 }

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

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

01610 {
01611    mode_t   mode = VOICEMAIL_DIR_MODE;
01612    int res;
01613 
01614    make_dir(dest, len, context, ext, folder);
01615    if ((res = ast_mkdir(dest, mode))) {
01616       ast_log(AST_LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res));
01617       return -1;
01618    }
01619    return 0;
01620 }

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

Definition at line 12737 of file app_voicemail_imapstorage.c.

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

12738 {
12739    int cmd = 0;
12740    char destination[80] = "";
12741    int retries = 0;
12742 
12743    if (!num) {
12744       ast_verb(3, "Destination number will be entered manually\n");
12745       while (retries < 3 && cmd != 't') {
12746          destination[1] = '\0';
12747          destination[0] = cmd = ast_play_and_wait(chan, "vm-enter-num-to-call");
12748          if (!cmd)
12749             destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
12750          if (!cmd)
12751             destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
12752          if (!cmd) {
12753             cmd = ast_waitfordigit(chan, 6000);
12754             if (cmd)
12755                destination[0] = cmd;
12756          }
12757          if (!cmd) {
12758             retries++;
12759          } else {
12760 
12761             if (cmd < 0)
12762                return 0;
12763             if (cmd == '*') {
12764                ast_verb(3, "User hit '*' to cancel outgoing call\n");
12765                return 0;
12766             }
12767             if ((cmd = ast_readstring(chan, destination + strlen(destination), sizeof(destination) - 1, 6000, 10000, "#")) < 0) 
12768                retries++;
12769             else
12770                cmd = 't';
12771          }
12772       }
12773       if (retries >= 3) {
12774          return 0;
12775       }
12776       
12777    } else {
12778       if (option_verbose > 2)
12779          ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
12780       ast_copy_string(destination, num, sizeof(destination));
12781    }
12782 
12783    if (!ast_strlen_zero(destination)) {
12784       if (destination[strlen(destination) -1 ] == '*')
12785          return 0; 
12786       if (option_verbose > 2)
12787          ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
12788       ast_copy_string(chan->exten, destination, sizeof(chan->exten));
12789       ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
12790       chan->priority = 0;
12791       return 9;
12792    }
12793    return 0;
12794 }

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

Definition at line 10455 of file app_voicemail_imapstorage.c.

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

10456 {
10457    struct ast_vm_user *vmu;
10458 
10459    AST_LIST_TRAVERSE(&users, vmu, list) {
10460       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(box, vmu->mailbox)) {
10461          if (strcasecmp(vmu->context, context)) {
10462             ast_log(LOG_WARNING, "\nIt has been detected that you have defined mailbox '%s' in separate\
10463                   \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10464                   \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10465                   \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10466          }
10467          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s\n", box);
10468          return NULL;
10469       }
10470       if (!strcasecmp(context, vmu->context) && !strcasecmp(box, vmu->mailbox)) {
10471          ast_log(LOG_WARNING, "Ignoring duplicated mailbox %s in context %s\n", box, context);
10472          return NULL;
10473       }
10474    }
10475    
10476    if (!(vmu = ast_calloc(1, sizeof(*vmu))))
10477       return NULL;
10478    
10479    ast_copy_string(vmu->context, context, sizeof(vmu->context));
10480    ast_copy_string(vmu->mailbox, box, sizeof(vmu->mailbox));
10481 
10482    AST_LIST_INSERT_TAIL(&users, vmu, list);
10483    
10484    return vmu;
10485 }

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 1370 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_test_flag, find_user_realtime(), globalflags, ast_vm_user::list, VM_ALLOCED, and VM_SEARCH.

01371 {
01372    /* This function could be made to generate one from a database, too */
01373    struct ast_vm_user *vmu = NULL, *cur;
01374    AST_LIST_LOCK(&users);
01375 
01376    if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
01377       context = "default";
01378 
01379    AST_LIST_TRAVERSE(&users, cur, list) {
01380 #ifdef IMAP_STORAGE
01381       if (cur->imapversion != imapversion) {
01382          continue;
01383       }
01384 #endif
01385       if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
01386          break;
01387       if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
01388          break;
01389    }
01390    if (cur) {
01391       /* Make a copy, so that on a reload, we have no race */
01392       if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
01393          memcpy(vmu, cur, sizeof(*vmu));
01394          ast_set2_flag(vmu, !ivm, VM_ALLOCED);
01395          AST_LIST_NEXT(vmu, list) = NULL;
01396       }
01397    } else
01398       vmu = find_user_realtime(ivm, context, mailbox);
01399    AST_LIST_UNLOCK(&users);
01400    return vmu;
01401 }

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

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

01334 {
01335    struct ast_variable *var;
01336    struct ast_vm_user *retval;
01337 
01338    if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
01339       if (!ivm)
01340          ast_set_flag(retval, VM_ALLOCED);   
01341       else
01342          memset(retval, 0, sizeof(*retval));
01343       if (mailbox) 
01344          ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
01345       populate_defaults(retval);
01346       if (!context && ast_test_flag((&globalflags), VM_SEARCH))
01347          var = ast_load_realtime("voicemail", "mailbox", mailbox, SENTINEL);
01348       else
01349          var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL);
01350       if (var) {
01351          apply_options_full(retval, var);
01352          ast_variables_destroy(var);
01353       } else { 
01354          if (!ivm) 
01355             ast_free(retval);
01356          retval = NULL;
01357       }  
01358    } 
01359    return retval;
01360 }

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 6979 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_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(), 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(), and VM_FWDURGAUTO.

06980 {
06981 #ifdef IMAP_STORAGE
06982    int todircount = 0;
06983    struct vm_state *dstvms;
06984 #endif
06985    char username[70]="";
06986    char fn[PATH_MAX]; /* for playback of name greeting */
06987    char ecodes[16] = "#";
06988    int res = 0, cmd = 0;
06989    struct ast_vm_user *receiver = NULL, *vmtmp;
06990    AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
06991    char *stringp;
06992    const char *s;
06993    int saved_messages = 0;
06994    int valid_extensions = 0;
06995    char *dir;
06996    int curmsg;
06997    char urgent_str[7] = "";
06998    char tmptxtfile[PATH_MAX];
06999    int prompt_played = 0;
07000 #ifndef IMAP_STORAGE
07001    char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
07002 #endif
07003    if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) {
07004       ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str));
07005    }
07006 
07007    if (vms == NULL) return -1;
07008    dir = vms->curdir;
07009    curmsg = vms->curmsg;
07010 
07011    tmptxtfile[0] = '\0';
07012    while (!res && !valid_extensions) {
07013       int use_directory = 0;
07014       if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
07015          int done = 0;
07016          int retries = 0;
07017          cmd = 0;
07018          while ((cmd >= 0) && !done ){
07019             if (cmd)
07020                retries = 0;
07021             switch (cmd) {
07022             case '1': 
07023                use_directory = 0;
07024                done = 1;
07025                break;
07026             case '2': 
07027                use_directory = 1;
07028                done = 1;
07029                break;
07030             case '*': 
07031                cmd = 't';
07032                done = 1;
07033                break;
07034             default: 
07035                /* Press 1 to enter an extension press 2 to use the directory */
07036                cmd = ast_play_and_wait(chan, "vm-forward");
07037                if (!cmd)
07038                   cmd = ast_waitfordigit(chan, 3000);
07039                if (!cmd)
07040                   retries++;
07041                if (retries > 3) {
07042                   cmd = 't';
07043                   done = 1;
07044                }
07045                
07046             }
07047          }
07048          if (cmd < 0 || cmd == 't')
07049             break;
07050       }
07051       
07052       if (use_directory) {
07053          /* use app_directory */
07054          
07055          char old_context[sizeof(chan->context)];
07056          char old_exten[sizeof(chan->exten)];
07057          int old_priority;
07058          struct ast_app* directory_app;
07059 
07060          directory_app = pbx_findapp("Directory");
07061          if (directory_app) {
07062             char vmcontext[256];
07063             /* make backup copies */
07064             memcpy(old_context, chan->context, sizeof(chan->context));
07065             memcpy(old_exten, chan->exten, sizeof(chan->exten));
07066             old_priority = chan->priority;
07067             
07068             /* call the the Directory, changes the channel */
07069             snprintf(vmcontext, sizeof(vmcontext), "%s,,v", context ? context : "default");
07070             res = pbx_exec(chan, directory_app, vmcontext);
07071             
07072             ast_copy_string(username, chan->exten, sizeof(username));
07073             
07074             /* restore the old context, exten, and priority */
07075             memcpy(chan->context, old_context, sizeof(chan->context));
07076             memcpy(chan->exten, old_exten, sizeof(chan->exten));
07077             chan->priority = old_priority;
07078          } else {
07079             ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
07080             ast_clear_flag((&globalflags), VM_DIRECFORWARD);
07081          }
07082       } else {
07083          /* Ask for an extension */
07084          res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
07085          prompt_played++;
07086          if (res || prompt_played > 4)
07087             break;
07088          if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
07089             break;
07090       }
07091       
07092       /* start all over if no username */
07093       if (ast_strlen_zero(username))
07094          continue;
07095       stringp = username;
07096       s = strsep(&stringp, "*");
07097       /* start optimistic */
07098       valid_extensions = 1;
07099       while (s) {
07100          if ((is_new_message == 1 || strcmp(s, sender->mailbox)) && (receiver = find_user(NULL, context, s))) {
07101             int oldmsgs;
07102             int newmsgs;
07103             int capacity;
07104             if (inboxcount(s, &newmsgs, &oldmsgs)) {
07105                ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", s);
07106                /* Shouldn't happen, but allow trying another extension if it does */
07107                res = ast_play_and_wait(chan, "pbx-invalid");
07108                valid_extensions = 0;
07109                break;
07110             }
07111             capacity = receiver->maxmsg - inprocess_count(receiver->mailbox, receiver->context, +1);
07112             if ((newmsgs + oldmsgs) >= capacity) {
07113                ast_log(LOG_NOTICE, "Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
07114                res = ast_play_and_wait(chan, "vm-mailboxfull");
07115                valid_extensions = 0;
07116                while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07117                   inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07118                   free_user(vmtmp);
07119                }
07120                inprocess_count(receiver->mailbox, receiver->context, -1);
07121                break;
07122             }
07123             AST_LIST_INSERT_HEAD(&extensions, receiver, list);
07124          } else {
07125             /* XXX Optimization for the future.  When we encounter a single bad extension,
07126              * bailing out on all of the extensions may not be the way to go.  We should
07127              * probably just bail on that single extension, then allow the user to enter
07128              * several more. XXX
07129              */
07130             while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07131                free_user(receiver);
07132             }
07133             ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
07134             /* "I am sorry, that's not a valid extension.  Please try again." */
07135             res = ast_play_and_wait(chan, "pbx-invalid");
07136             valid_extensions = 0;
07137             break;
07138          }
07139 
07140          /* play name if available, else play extension number */
07141          snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s);
07142          RETRIEVE(fn, -1, s, receiver->context);
07143          if (ast_fileexists(fn, NULL, NULL) > 0) {
07144             res = ast_stream_and_wait(chan, fn, ecodes);
07145             if (res) {
07146                DISPOSE(fn, -1);
07147                return res;
07148             }
07149          } else {
07150             res = ast_say_digit_str(chan, s, ecodes, chan->language);
07151          }
07152          DISPOSE(fn, -1);
07153 
07154          s = strsep(&stringp, "*");
07155       }
07156       /* break from the loop of reading the extensions */
07157       if (valid_extensions)
07158          break;
07159    }
07160    /* check if we're clear to proceed */
07161    if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
07162       return res;
07163    if (is_new_message == 1) {
07164       struct leave_vm_options leave_options;
07165       char mailbox[AST_MAX_EXTENSION * 2 + 2];
07166       snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
07167 
07168       /* Send VoiceMail */
07169       memset(&leave_options, 0, sizeof(leave_options));
07170       leave_options.record_gain = record_gain;
07171       cmd = leave_voicemail(chan, mailbox, &leave_options);
07172    } else {
07173       /* Forward VoiceMail */
07174       long duration = 0;
07175       struct vm_state vmstmp;
07176       int copy_msg_result = 0;
07177       memcpy(&vmstmp, vms, sizeof(vmstmp));
07178 
07179       RETRIEVE(dir, curmsg, sender->mailbox, sender->context);
07180 
07181       cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str);
07182       if (!cmd) {
07183          AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
07184 #ifdef IMAP_STORAGE
07185             int attach_user_voicemail;
07186             char *myserveremail = serveremail;
07187             
07188             /* get destination mailbox */
07189             dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
07190             if (!dstvms) {
07191                dstvms = create_vm_state_from_user(vmtmp);
07192             }
07193             if (dstvms) {
07194                init_mailstream(dstvms, 0);
07195                if (!dstvms->mailstream) {
07196                   ast_log(AST_LOG_ERROR, "IMAP mailstream for %s is NULL\n", vmtmp->mailbox);
07197                } else {
07198                   copy_msg_result = STORE(vmstmp.curdir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
07199                   run_externnotify(vmtmp->context, vmtmp->mailbox, urgent_str); 
07200                }
07201             } else {
07202                ast_log(AST_LOG_ERROR, "Could not find state information for mailbox %s\n", vmtmp->mailbox);
07203             }
07204             if (!ast_strlen_zero(vmtmp->serveremail))
07205                myserveremail = vmtmp->serveremail;
07206             attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
07207             /* NULL category for IMAP storage */
07208             sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
07209                dstvms->curbox,
07210                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
07211                S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
07212                vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
07213                NULL, urgent_str);
07214 #else
07215             copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
07216 #endif
07217             saved_messages++;
07218             AST_LIST_REMOVE_CURRENT(list);
07219             inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07220             free_user(vmtmp);
07221             if (res)
07222                break;
07223          }
07224          AST_LIST_TRAVERSE_SAFE_END;
07225          if (saved_messages > 0 && !copy_msg_result) {
07226             /* give confirmation that the message was saved */
07227             /* commented out since we can't forward batches yet
07228             if (saved_messages == 1)
07229                res = ast_play_and_wait(chan, "vm-message");
07230             else
07231                res = ast_play_and_wait(chan, "vm-messages");
07232             if (!res)
07233                res = ast_play_and_wait(chan, "vm-saved"); */
07234 #ifdef IMAP_STORAGE
07235             /* If forwarded with intro, DON'T PLAY THIS MESSAGE AGAIN! */
07236             if (ast_strlen_zero(vmstmp.introfn))
07237 #endif
07238             res = ast_play_and_wait(chan, "vm-msgsaved");
07239          }
07240 #ifndef IMAP_STORAGE
07241          else {
07242             /* with IMAP, mailbox full warning played by imap_check_limits */
07243             res = ast_play_and_wait(chan, "vm-mailboxfull");
07244          }
07245          /* Restore original message without prepended message if backup exists */
07246          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07247          strcpy(textfile, msgfile);
07248          strcpy(backup, msgfile);
07249          strcpy(backup_textfile, msgfile);
07250          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07251          strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
07252          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07253          if (ast_fileexists(backup, NULL, NULL) > 0) {
07254             ast_filerename(backup, msgfile, NULL);
07255             rename(backup_textfile, textfile);
07256          }
07257 #endif
07258       }
07259       DISPOSE(dir, curmsg);
07260 #ifndef IMAP_STORAGE
07261       if (cmd) { /* assuming hangup, cleanup backup file */
07262          make_file(msgfile, sizeof(msgfile), dir, curmsg);
07263          strcpy(textfile, msgfile);
07264          strcpy(backup_textfile, msgfile);
07265          strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
07266          strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
07267          rename(backup_textfile, textfile);
07268       }
07269 #endif
07270    }
07271 
07272    /* If anything failed above, we still have this list to free */
07273    while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list))) {
07274       inprocess_count(vmtmp->mailbox, vmtmp->context, -1);
07275       free_user(vmtmp);
07276    }
07277    return res ? res : cmd;
07278 }

static void free_user ( struct ast_vm_user vmu  )  [static]

Definition at line 1664 of file app_voicemail_imapstorage.c.

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

01665 {
01666    if (ast_test_flag(vmu, VM_ALLOCED)) {
01667       if (vmu->emailbody != NULL) {
01668          ast_free(vmu->emailbody);
01669          vmu->emailbody = NULL;
01670       }
01671       if (vmu->emailsubject != NULL) {
01672          ast_free(vmu->emailsubject);
01673          vmu->emailsubject = NULL;
01674       }
01675       ast_free(vmu);
01676    }
01677 }

static void free_vm_users ( void   )  [static]

Free the users structure.

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

11448 {
11449    struct ast_vm_user *current;
11450    AST_LIST_LOCK(&users);
11451    while ((current = AST_LIST_REMOVE_HEAD(&users, list))) {
11452       ast_set_flag(current, VM_ALLOCED);
11453       free_user(current);
11454    }
11455    AST_LIST_UNLOCK(&users);
11456 }

static void free_vm_zones ( void   )  [static]

Free the zones structure.

Definition at line 11459 of file app_voicemail_imapstorage.c.

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

11460 {
11461    struct vm_zone *zcur;
11462    AST_LIST_LOCK(&zones);
11463    while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
11464       free_zone(zcur);
11465    AST_LIST_UNLOCK(&zones);
11466 }

static void free_zone ( struct vm_zone z  )  [static]

Definition at line 4949 of file app_voicemail_imapstorage.c.

References ast_free.

04950 {
04951    ast_free(z);
04952 }

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

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

04906 {
04907    struct ast_tm tm;
04908    struct timeval t = ast_tvnow();
04909    
04910    ast_localtime(&t, &tm, "UTC");
04911 
04912    return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm);
04913 }

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

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

06619 {
06620    int x;
06621    int d;
06622    char fn[PATH_MAX];
06623    d = ast_play_and_wait(chan, "vm-press");  /* "Press" */
06624    if (d)
06625       return d;
06626    for (x = start; x < 5; x++) { /* For all folders */
06627       if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, NULL)))
06628          return d;
06629       d = ast_play_and_wait(chan, "vm-for"); /* "for" */
06630       if (d)
06631          return d;
06632       snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x));  /* Folder name */
06633       d = vm_play_folder_name(chan, fn);
06634       if (d)
06635          return d;
06636       d = ast_waitfordigit(chan, 500);
06637       if (d)
06638          return d;
06639    }
06640    d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
06641    if (d)
06642       return d;
06643    d = ast_waitfordigit(chan, 4000);
06644    return d;
06645 }

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

References ast_play_and_wait(), and get_folder().

06660 {
06661    int res = 0;
06662    int loops = 0;
06663    res = ast_play_and_wait(chan, fn);  /* Folder name */
06664    while (((res < '0') || (res > '9')) &&
06665          (res != '#') && (res >= 0) &&
06666          loops < 4) {
06667       res = get_folder(chan, 0);
06668       loops++;
06669    }
06670    if (loops == 4) { /* give up */
06671       return '#';
06672    }
06673    return res;
06674 }

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

Definition at line 1651 of file app_voicemail_imapstorage.c.

References ARRAY_LEN.

01652 {
01653    size_t i;
01654 
01655    for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
01656       if (strcasecmp(name, mailbox_folders[i]) == 0) {
01657          return i;
01658       }
01659    }
01660 
01661    return -1;
01662 }

static int handle_subscribe ( void *  datap  )  [static]

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

11231 {
11232    unsigned int len;
11233    struct mwi_sub *mwi_sub;
11234    struct mwi_sub_task *p = datap;
11235 
11236    len = sizeof(*mwi_sub);
11237    if (!ast_strlen_zero(p->mailbox))
11238       len += strlen(p->mailbox);
11239 
11240    if (!ast_strlen_zero(p->context))
11241       len += strlen(p->context) + 1; /* Allow for seperator */
11242 
11243    if (!(mwi_sub = ast_calloc(1, len)))
11244       return -1;
11245 
11246    mwi_sub->uniqueid = p->uniqueid;
11247    if (!ast_strlen_zero(p->mailbox))
11248       strcpy(mwi_sub->mailbox, p->mailbox);
11249 
11250    if (!ast_strlen_zero(p->context)) {
11251       strcat(mwi_sub->mailbox, "@");
11252       strcat(mwi_sub->mailbox, p->context);
11253    }
11254 
11255    AST_RWLIST_WRLOCK(&mwi_subs);
11256    AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);
11257    AST_RWLIST_UNLOCK(&mwi_subs);
11258    ast_free((void *) p->mailbox);
11259    ast_free((void *) p->context);
11260    ast_free(p);
11261    poll_subscribed_mailbox(mwi_sub);
11262    return 0;
11263 }

static int handle_unsubscribe ( void *  datap  )  [static]

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

11209 {
11210    struct mwi_sub *mwi_sub;
11211    uint32_t *uniqueid = datap;
11212    
11213    AST_RWLIST_WRLOCK(&mwi_subs);
11214    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {
11215       if (mwi_sub->uniqueid == *uniqueid) {
11216          AST_LIST_REMOVE_CURRENT(entry);
11217          break;
11218       }
11219    }
11220    AST_RWLIST_TRAVERSE_SAFE_END
11221    AST_RWLIST_UNLOCK(&mwi_subs);
11222 
11223    if (mwi_sub)
11224       mwi_sub_destroy(mwi_sub);
11225 
11226    ast_free(uniqueid);  
11227    return 0;
11228 }

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

10984 {
10985    switch (cmd) {
10986    case CLI_INIT:
10987       e->command = "voicemail reload";
10988       e->usage =
10989          "Usage: voicemail reload\n"
10990          "       Reload voicemail configuration\n";
10991       return NULL;
10992    case CLI_GENERATE:
10993       return NULL;
10994    }
10995 
10996    if (a->argc != 2)
10997       return CLI_SHOWUSAGE;
10998 
10999    ast_cli(a->fd, "Reloading voicemail configuration...\n");   
11000    load_config(1);
11001    
11002    return CLI_SUCCESS;
11003 }

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

10874 {
10875    struct ast_vm_user *vmu;
10876 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
10877    const char *context = NULL;
10878    int users_counter = 0;
10879 
10880    switch (cmd) {
10881    case CLI_INIT:
10882       e->command = "voicemail show users";
10883       e->usage =
10884          "Usage: voicemail show users [for <context>]\n"
10885          "       Lists all mailboxes currently set up\n";
10886       return NULL;
10887    case CLI_GENERATE:
10888       return complete_voicemail_show_users(a->line, a->word, a->pos, a->n);
10889    }  
10890 
10891    if ((a->argc < 3) || (a->argc > 5) || (a->argc == 4))
10892       return CLI_SHOWUSAGE;
10893    if (a->argc == 5) {
10894       if (strcmp(a->argv[3],"for"))
10895          return CLI_SHOWUSAGE;
10896       context = a->argv[4];
10897    }
10898 
10899    if (ast_check_realtime("voicemail")) {
10900       if (!context) {
10901          ast_cli(a->fd, "You must specify a specific context to show users from realtime!\n");
10902          return CLI_SHOWUSAGE;
10903       }
10904       return show_users_realtime(a->fd, context);
10905    }
10906 
10907    AST_LIST_LOCK(&users);
10908    if (AST_LIST_EMPTY(&users)) {
10909       ast_cli(a->fd, "There are no voicemail users currently defined\n");
10910       AST_LIST_UNLOCK(&users);
10911       return CLI_FAILURE;
10912    }
10913    if (a->argc == 3)
10914       ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10915    else {
10916       int count = 0;
10917       AST_LIST_TRAVERSE(&users, vmu, list) {
10918          if (!strcmp(context, vmu->context))
10919             count++;
10920       }
10921       if (count) {
10922          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, "Context", "Mbox", "User", "Zone", "NewMsg");
10923       } else {
10924          ast_cli(a->fd, "No such voicemail context \"%s\"\n", context);
10925          AST_LIST_UNLOCK(&users);
10926          return CLI_FAILURE;
10927       }
10928    }
10929    AST_LIST_TRAVERSE(&users, vmu, list) {
10930       int newmsgs = 0, oldmsgs = 0;
10931       char count[12], tmp[256] = "";
10932 
10933       if ((a->argc == 3) || ((a->argc == 5) && !strcmp(context, vmu->context))) {
10934          snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
10935          inboxcount(tmp, &newmsgs, &oldmsgs);
10936          snprintf(count, sizeof(count), "%d", newmsgs);
10937          ast_cli(a->fd, HVSU_OUTPUT_FORMAT, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
10938          users_counter++;
10939       }
10940    }
10941    AST_LIST_UNLOCK(&users);
10942    ast_cli(a->fd, "%d voicemail users configured.\n", users_counter);
10943    return CLI_SUCCESS;
10944 }

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

10948 {
10949    struct vm_zone *zone;
10950 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
10951    char *res = CLI_SUCCESS;
10952 
10953    switch (cmd) {
10954    case CLI_INIT:
10955       e->command = "voicemail show zones";
10956       e->usage =
10957          "Usage: voicemail show zones\n"
10958          "       Lists zone message formats\n";
10959       return NULL;
10960    case CLI_GENERATE:
10961       return NULL;
10962    }
10963 
10964    if (a->argc != 3)
10965       return CLI_SHOWUSAGE;
10966 
10967    AST_LIST_LOCK(&zones);
10968    if (!AST_LIST_EMPTY(&zones)) {
10969       ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, "Zone", "Timezone", "Message Format");
10970       AST_LIST_TRAVERSE(&zones, zone, list) {
10971          ast_cli(a->fd, HVSZ_OUTPUT_FORMAT, zone->name, zone->timezone, zone->msg_format);
10972       }
10973    } else {
10974       ast_cli(a->fd, "There are no voicemail zones currently defined\n");
10975       res = CLI_FAILURE;
10976    }
10977    AST_LIST_UNLOCK(&zones);
10978 
10979    return res;
10980 }

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

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

05292 {
05293    char tmp[256], *tmp2 = tmp, *box, *context;
05294    ast_copy_string(tmp, mailbox, sizeof(tmp));
05295    if (ast_strlen_zero(folder)) {
05296       folder = "INBOX";
05297    }
05298    while ((box = strsep(&tmp2, ",&"))) {
05299       if ((context = strchr(box, '@')))
05300          *context++ = '\0';
05301       else
05302          context = "default";
05303       if (__has_voicemail(context, box, folder, 1))
05304          return 1;
05305       /* If we are checking INBOX, we should check Urgent as well */
05306       if (!strcmp(folder, "INBOX") && __has_voicemail(context, box, "Urgent", 1)) {
05307          return 1;
05308       }
05309    }
05310    return 0;
05311 }

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

Definition at line 5373 of file app_voicemail_imapstorage.c.

References inboxcount2().

05374 {
05375    int urgentmsgs = 0;
05376    int res = inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
05377    if (newmsgs) {
05378       *newmsgs += urgentmsgs;
05379    }
05380    return res;
05381 }

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

Definition at line 5314 of file app_voicemail_imapstorage.c.

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

05315 {
05316    char tmp[256];
05317    char *context;
05318 
05319    /* If no mailbox, return immediately */
05320    if (ast_strlen_zero(mailbox))
05321       return 0;
05322 
05323    if (newmsgs)
05324       *newmsgs = 0;
05325    if (oldmsgs)
05326       *oldmsgs = 0;
05327    if (urgentmsgs)
05328       *urgentmsgs = 0;
05329 
05330    if (strchr(mailbox, ',')) {
05331       int tmpnew, tmpold, tmpurgent;
05332       char *mb, *cur;
05333 
05334       ast_copy_string(tmp, mailbox, sizeof(tmp));
05335       mb = tmp;
05336       while ((cur = strsep(&mb, ", "))) {
05337          if (!ast_strlen_zero(cur)) {
05338             if (inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
05339                return -1;
05340             else {
05341                if (newmsgs)
05342                   *newmsgs += tmpnew; 
05343                if (oldmsgs)
05344                   *oldmsgs += tmpold;
05345                if (urgentmsgs)
05346                   *urgentmsgs += tmpurgent;
05347             }
05348          }
05349       }
05350       return 0;
05351    }
05352 
05353    ast_copy_string(tmp, mailbox, sizeof(tmp));
05354    
05355    if ((context = strchr(tmp, '@')))
05356       *context++ = '\0';
05357    else
05358       context = "default";
05359 
05360    if (newmsgs)
05361       *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
05362    if (oldmsgs)
05363       *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
05364    if (urgentmsgs)
05365       *urgentmsgs = __has_voicemail(context, tmp, "Urgent", 0);
05366 
05367    return 0;
05368 }

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

utility used by inchar(), for base_encode()

Definition at line 4077 of file app_voicemail_imapstorage.c.

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

04078 {
04079    int l;
04080 
04081    if (bio->ateof)
04082       return 0;
04083 
04084    if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) <= 0) {
04085       if (ferror(fi))
04086          return -1;
04087 
04088       bio->ateof = 1;
04089       return 0;
04090    }
04091 
04092    bio->iolen = l;
04093    bio->iocp = 0;
04094 
04095    return 1;
04096 }

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

utility used by base_encode()

Definition at line 4101 of file app_voicemail_imapstorage.c.

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

04102 {
04103    if (bio->iocp>=bio->iolen) {
04104       if (!inbuf(bio, fi))
04105          return EOF;
04106    }
04107 
04108    return bio->iobuf[bio->iocp++];
04109 }

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

Definition at line 891 of file app_voicemail_imapstorage.c.

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

00892 {
00893    struct inprocess *i = obj, *j = arg;
00894    if (strcmp(i->mailbox, j->mailbox)) {
00895       return 0;
00896    }
00897    return !strcmp(i->context, j->context) ? CMP_MATCH : 0;
00898 }

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

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

00901 {
00902    struct inprocess *i, *arg = alloca(sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
00903    arg->context = arg->mailbox + strlen(mailbox) + 1;
00904    strcpy(arg->mailbox, mailbox); /* SAFE */
00905    strcpy(arg->context, context); /* SAFE */
00906    ao2_lock(inprocess_container);
00907    if ((i = ao2_find(inprocess_container, arg, 0))) {
00908       int ret = ast_atomic_fetchadd_int(&i->count, delta);
00909       ao2_unlock(inprocess_container);
00910       ao2_ref(i, -1);
00911       return ret;
00912    }
00913    if (delta < 0) {
00914       ast_log(LOG_WARNING, "BUG: ref count decrement on non-existing object???\n");
00915    }
00916    if (!(i = ao2_alloc(sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
00917       ao2_unlock(inprocess_container);
00918       return 0;
00919    }
00920    i->context = i->mailbox + strlen(mailbox) + 1;
00921    strcpy(i->mailbox, mailbox); /* SAFE */
00922    strcpy(i->context, context); /* SAFE */
00923    i->count = delta;
00924    ao2_link(inprocess_container, i);
00925    ao2_unlock(inprocess_container);
00926    ao2_ref(i, -1);
00927    return 0;
00928 }

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

Definition at line 885 of file app_voicemail_imapstorage.c.

References inprocess::mailbox.

00886 {
00887    const struct inprocess *i = obj;
00888    return atoi(i->mailbox);
00889 }

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

Definition at line 4915 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, and RETRIEVE.

04916 {
04917    int res;
04918    char fn[PATH_MAX];
04919    char dest[PATH_MAX];
04920 
04921    snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
04922 
04923    if ((res = create_dirpath(dest, sizeof(dest), context, ext, ""))) {
04924       ast_log(AST_LOG_WARNING, "Failed to make directory(%s)\n", fn);
04925       return -1;
04926    }
04927 
04928    RETRIEVE(fn, -1, ext, context);
04929    if (ast_fileexists(fn, NULL, NULL) > 0) {
04930       res = ast_stream_and_wait(chan, fn, ecodes);
04931       if (res) {
04932          DISPOSE(fn, -1);
04933          return res;
04934       }
04935    } else {
04936       /* Dispose just in case */
04937       DISPOSE(fn, -1);
04938       res = ast_stream_and_wait(chan, "vm-theperson", ecodes);
04939       if (res)
04940          return res;
04941       res = ast_say_digit_str(chan, ext, ecodes, chan->language);
04942       if (res)
04943          return res;
04944    }
04945    res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes);
04946    return res;
04947 }

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

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

01309 {
01310    int i;
01311    char *local_key = ast_strdupa(key);
01312 
01313    for (i = 0; i < strlen(key); ++i) {
01314       if (!strchr(VALID_DTMF, *local_key)) {
01315          ast_log(AST_LOG_WARNING, "Invalid DTMF key \"%c\" used in voicemail configuration file\n", *local_key);
01316          return 0;
01317       }
01318       local_key++;
01319    }
01320    return 1;
01321 }

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

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

03896 {
03897    int x;
03898    unsigned char map[MAXMSGLIMIT] = "";
03899    DIR *msgdir;
03900    struct dirent *msgdirent;
03901    int msgdirint;
03902    char extension[4];
03903    int stopcount = 0;
03904 
03905    /* Reading the entire directory into a file map scales better than
03906     * doing a stat repeatedly on a predicted sequence.  I suspect this
03907     * is partially due to stat(2) internally doing a readdir(2) itself to
03908     * find each file. */
03909    if (!(msgdir = opendir(dir))) {
03910       return -1;
03911    }
03912 
03913    while ((msgdirent = readdir(msgdir))) {
03914       if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) {
03915          map[msgdirint] = 1;
03916          stopcount++;
03917          ast_debug(4, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
03918       }
03919    }
03920    closedir(msgdir);
03921 
03922    for (x = 0; x < vmu->maxmsg; x++) {
03923       if (map[x] == 1) {
03924          stopcount--;
03925       } else if (map[x] == 0 && !stopcount) {
03926          break;
03927       }
03928    }
03929 
03930    return x - 1;
03931 }

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

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

05447 {
05448 #ifdef IMAP_STORAGE
05449    int newmsgs, oldmsgs;
05450 #else
05451    char urgdir[PATH_MAX];
05452 #endif
05453    char txtfile[PATH_MAX];
05454    char tmptxtfile[PATH_MAX];
05455    struct vm_state *vms = NULL;
05456    char callerid[256];
05457    FILE *txt;
05458    char date[256];
05459    int txtdes;
05460    int res = 0;
05461    int msgnum;
05462    int duration = 0;
05463    int ausemacro = 0;
05464    int ousemacro = 0;
05465    int ouseexten = 0;
05466    char tmpdur[16];
05467    char priority[16];
05468    char origtime[16];
05469    char dir[PATH_MAX];
05470    char tmpdir[PATH_MAX];
05471    char fn[PATH_MAX];
05472    char prefile[PATH_MAX] = "";
05473    char tempfile[PATH_MAX] = "";
05474    char ext_context[256] = "";
05475    char fmt[80];
05476    char *context;
05477    char ecodes[17] = "#";
05478    struct ast_str *tmp = ast_str_create(16);
05479    char *tmpptr;
05480    struct ast_vm_user *vmu;
05481    struct ast_vm_user svm;
05482    const char *category = NULL;
05483    const char *code;
05484    const char *alldtmf = "0123456789ABCD*#";
05485    char flag[80];
05486 
05487    if (!tmp) {
05488       return -1;
05489    }
05490 
05491    ast_str_set(&tmp, 0, "%s", ext);
05492    ext = ast_str_buffer(tmp);
05493    if ((context = strchr(ext, '@'))) {
05494       *context++ = '\0';
05495       tmpptr = strchr(context, '&');
05496    } else {
05497       tmpptr = strchr(ext, '&');
05498    }
05499 
05500    if (tmpptr)
05501       *tmpptr++ = '\0';
05502 
05503    ast_channel_lock(chan);
05504    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
05505       category = ast_strdupa(category);
05506    }
05507    ast_channel_unlock(chan);
05508 
05509    if (ast_test_flag(options, OPT_MESSAGE_Urgent)) {
05510       ast_copy_string(flag, "Urgent", sizeof(flag));
05511    } else if (ast_test_flag(options, OPT_MESSAGE_PRIORITY)) {
05512       ast_copy_string(flag, "PRIORITY", sizeof(flag));
05513    } else {
05514       flag[0] = '\0';
05515    }
05516 
05517    ast_debug(3, "Before find_user\n");
05518    if (!(vmu = find_user(&svm, context, ext))) {
05519       ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
05520       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05521       ast_free(tmp);
05522       return res;
05523    }
05524    /* Setup pre-file if appropriate */
05525    if (strcmp(vmu->context, "default"))
05526       snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
05527    else
05528       ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
05529 
05530    /* Set the path to the prefile. Will be one of 
05531       VM_SPOOL_DIRcontext/ext/busy
05532       VM_SPOOL_DIRcontext/ext/unavail
05533       Depending on the flag set in options.
05534    */
05535    if (ast_test_flag(options, OPT_BUSY_GREETING)) {
05536       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
05537    } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
05538       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
05539    }
05540    /* Set the path to the tmpfile as
05541       VM_SPOOL_DIR/context/ext/temp
05542       and attempt to create the folder structure.
05543    */
05544    snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
05545    if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) {
05546       ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
05547       ast_free(tmp);
05548       return -1;
05549    }
05550    RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context);
05551    if (ast_fileexists(tempfile, NULL, NULL) > 0)
05552       ast_copy_string(prefile, tempfile, sizeof(prefile));
05553 
05554    DISPOSE(tempfile, -1);
05555    /* It's easier just to try to make it than to check for its existence */
05556 #ifndef IMAP_STORAGE
05557    create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
05558 #else
05559    snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR);
05560    if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) {
05561       ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
05562    }
05563 #endif
05564 
05565    /* Check current or macro-calling context for special extensions */
05566    if (ast_test_flag(vmu, VM_OPERATOR)) {
05567       if (!ast_strlen_zero(vmu->exit)) {
05568          if (ast_exists_extension(chan, vmu->exit, "o", 1,
05569             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05570             strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05571             ouseexten = 1;
05572          }
05573       } else if (ast_exists_extension(chan, chan->context, "o", 1,
05574          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05575          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05576          ouseexten = 1;
05577       } else if (!ast_strlen_zero(chan->macrocontext)
05578          && ast_exists_extension(chan, chan->macrocontext, "o", 1,
05579             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05580          strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
05581          ousemacro = 1;
05582       }
05583    }
05584 
05585    if (!ast_strlen_zero(vmu->exit)) {
05586       if (ast_exists_extension(chan, vmu->exit, "a", 1,
05587          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05588          strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05589       }
05590    } else if (ast_exists_extension(chan, chan->context, "a", 1,
05591       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05592       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05593    } else if (!ast_strlen_zero(chan->macrocontext)
05594       && ast_exists_extension(chan, chan->macrocontext, "a", 1,
05595          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05596       strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
05597       ausemacro = 1;
05598    }
05599 
05600    if (ast_test_flag(options, OPT_DTMFEXIT)) {
05601       for (code = alldtmf; *code; code++) {
05602          char e[2] = "";
05603          e[0] = *code;
05604          if (strchr(ecodes, e[0]) == NULL
05605             && ast_canmatch_extension(chan, chan->context, e, 1,
05606                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
05607             strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
05608          }
05609       }
05610    }
05611 
05612    /* Play the beginning intro if desired */
05613    if (!ast_strlen_zero(prefile)) {
05614 #ifdef ODBC_STORAGE
05615       int success = 
05616 #endif
05617          RETRIEVE(prefile, -1, ext, context);
05618       if (ast_fileexists(prefile, NULL, NULL) > 0) {
05619          if (ast_streamfile(chan, prefile, chan->language) > -1) 
05620             res = ast_waitstream(chan, ecodes);
05621 #ifdef ODBC_STORAGE
05622          if (success == -1) {
05623             /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
05624             ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
05625             store_file(prefile, vmu->mailbox, vmu->context, -1);
05626          }
05627 #endif
05628       } else {
05629          ast_debug(1, "%s doesn't exist, doing what we can\n", prefile);
05630          res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
05631       }
05632       DISPOSE(prefile, -1);
05633       if (res < 0) {
05634          ast_debug(1, "Hang up during prefile playback\n");
05635          free_user(vmu);
05636          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05637          ast_free(tmp);
05638          return -1;
05639       }
05640    }
05641    if (res == '#') {
05642       /* On a '#' we skip the instructions */
05643       ast_set_flag(options, OPT_SILENT);
05644       res = 0;
05645    }
05646    /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */
05647    if (vmu->maxmsg == 0) {
05648       if (option_debug > 2)
05649          ast_log(LOG_DEBUG, "Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
05650       pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05651       goto leave_vm_out;
05652    }
05653    if (!res && !ast_test_flag(options, OPT_SILENT)) {
05654       res = ast_stream_and_wait(chan, INTRO, ecodes);
05655       if (res == '#') {
05656          ast_set_flag(options, OPT_SILENT);
05657          res = 0;
05658       }
05659    }
05660    if (res > 0)
05661       ast_stopstream(chan);
05662    /* Check for a '*' here in case the caller wants to escape from voicemail to something
05663     other than the operator -- an automated attendant or mailbox login for example */
05664    if (res == '*') {
05665       chan->exten[0] = 'a';
05666       chan->exten[1] = '\0';
05667       if (!ast_strlen_zero(vmu->exit)) {
05668          ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05669       } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
05670          ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05671       }
05672       chan->priority = 0;
05673       free_user(vmu);
05674       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05675       ast_free(tmp);
05676       return 0;
05677    }
05678 
05679    /* Check for a '0' here */
05680    if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') {
05681    transfer:
05682       if (ouseexten || ousemacro) {
05683          chan->exten[0] = 'o';
05684          chan->exten[1] = '\0';
05685          if (!ast_strlen_zero(vmu->exit)) {
05686             ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
05687          } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
05688             ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
05689          }
05690          ast_play_and_wait(chan, "transfer");
05691          chan->priority = 0;
05692          free_user(vmu);
05693          pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05694       }
05695       ast_free(tmp);
05696       return OPERATOR_EXIT;
05697    }
05698 
05699    /* Allow all other digits to exit Voicemail and return to the dialplan */
05700    if (ast_test_flag(options, OPT_DTMFEXIT) && res > 0) {
05701       if (!ast_strlen_zero(options->exitcontext))
05702          ast_copy_string(chan->context, options->exitcontext, sizeof(chan->context));
05703       free_user(vmu);
05704       pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
05705       ast_free(tmp);
05706       return res;
05707    }
05708 
05709    if (res < 0) {
05710       free_user(vmu);
05711       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05712       ast_free(tmp);
05713       return -1;
05714    }
05715    /* The meat of recording the message...  All the announcements and beeps have been played*/
05716    ast_copy_string(fmt, vmfmts, sizeof(fmt));
05717    if (!ast_strlen_zero(fmt)) {
05718       msgnum = 0;
05719 
05720 #ifdef IMAP_STORAGE
05721       /* Is ext a mailbox? */
05722       /* must open stream for this user to get info! */
05723       res = inboxcount(ext_context, &newmsgs, &oldmsgs);
05724       if (res < 0) {
05725          ast_log(AST_LOG_NOTICE, "Can not leave voicemail, unable to count messages\n");
05726          ast_free(tmp);
05727          return -1;
05728       }
05729       if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
05730       /* It is possible under certain circumstances that inboxcount did not
05731        * create a vm_state when it was needed. This is a catchall which will
05732        * rarely be used.
05733        */
05734          if (!(vms = create_vm_state_from_user(vmu))) {
05735             ast_log(AST_LOG_ERROR, "Couldn't allocate necessary space\n");
05736             ast_free(tmp);
05737             return -1;
05738          }
05739       }
05740       vms->newmessages++;
05741       
05742       /* here is a big difference! We add one to it later */
05743       msgnum = newmsgs + oldmsgs;
05744       ast_debug(3, "Messagecount set to %d\n", msgnum);
05745       snprintf(fn, sizeof(fn), "%simap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
05746       /* set variable for compatibility */
05747       pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05748 
05749       if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
05750          goto leave_vm_out;
05751       }
05752 #else
05753       if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) {
05754          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05755          if (!res)
05756             res = ast_waitstream(chan, "");
05757          ast_log(AST_LOG_WARNING, "No more messages possible\n");
05758          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05759          inprocess_count(vmu->mailbox, vmu->context, -1);
05760          goto leave_vm_out;
05761       }
05762 
05763 #endif
05764       snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
05765       txtdes = mkstemp(tmptxtfile);
05766       chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
05767       if (txtdes < 0) {
05768          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05769          if (!res)
05770             res = ast_waitstream(chan, "");
05771          ast_log(AST_LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
05772          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05773          inprocess_count(vmu->mailbox, vmu->context, -1);
05774          goto leave_vm_out;
05775       }
05776 
05777       /* Now play the beep once we have the message number for our next message. */
05778       if (res >= 0) {
05779          /* Unless we're *really* silent, try to send the beep */
05780          res = ast_stream_and_wait(chan, "beep", "");
05781       }
05782             
05783       /* Store information in real-time storage */
05784       if (ast_check_realtime("voicemail_data")) {
05785          snprintf(priority, sizeof(priority), "%d", chan->priority);
05786          snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
05787          get_date(date, sizeof(date));
05788          ast_callerid_merge(callerid, sizeof(callerid),
05789             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05790             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05791             "Unknown");
05792          ast_store_realtime("voicemail_data",
05793             "origmailbox", ext,
05794             "context", chan->context,
05795             "macrocontext", chan->macrocontext,
05796             "exten", chan->exten,
05797             "priority", priority,
05798             "callerchan", chan->name,
05799             "callerid", callerid,
05800             "origdate", date,
05801             "origtime", origtime,
05802             "category", S_OR(category, ""),
05803             "filename", tmptxtfile,
05804             SENTINEL);
05805       }
05806 
05807       /* Store information */
05808       txt = fdopen(txtdes, "w+");
05809       if (txt) {
05810          get_date(date, sizeof(date));
05811          ast_callerid_merge(callerid, sizeof(callerid),
05812             S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05813             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05814             "Unknown");
05815          fprintf(txt, 
05816             ";\n"
05817             "; Message Information file\n"
05818             ";\n"
05819             "[message]\n"
05820             "origmailbox=%s\n"
05821             "context=%s\n"
05822             "macrocontext=%s\n"
05823             "exten=%s\n"
05824             "rdnis=%s\n"
05825             "priority=%d\n"
05826             "callerchan=%s\n"
05827             "callerid=%s\n"
05828             "origdate=%s\n"
05829             "origtime=%ld\n"
05830             "category=%s\n",
05831             ext,
05832             chan->context,
05833             chan->macrocontext, 
05834             chan->exten,
05835             S_COR(chan->redirecting.from.number.valid,
05836                chan->redirecting.from.number.str, "unknown"),
05837             chan->priority,
05838             chan->name,
05839             callerid,
05840             date, (long) time(NULL),
05841             category ? category : "");
05842       } else {
05843          ast_log(AST_LOG_WARNING, "Error opening text file for output\n");
05844          inprocess_count(vmu->mailbox, vmu->context, -1);
05845          if (ast_check_realtime("voicemail_data")) {
05846             ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05847          }
05848          res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
05849          goto leave_vm_out;
05850       }
05851       res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, NULL, options->record_gain, vms, flag);
05852 
05853       if (txt) {
05854          fprintf(txt, "flag=%s\n", flag);
05855          if (duration < vmu->minsecs) {
05856             fclose(txt);
05857             ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmu->minsecs);
05858             ast_filedelete(tmptxtfile, NULL);
05859             unlink(tmptxtfile);
05860             if (ast_check_realtime("voicemail_data")) {
05861                ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05862             }
05863             inprocess_count(vmu->mailbox, vmu->context, -1);
05864          } else {
05865             fprintf(txt, "duration=%d\n", duration);
05866             fclose(txt);
05867             if (vm_lock_path(dir)) {
05868                ast_log(AST_LOG_ERROR, "Couldn't lock directory %s.  Voicemail will be lost.\n", dir);
05869                /* Delete files */
05870                ast_filedelete(tmptxtfile, NULL);
05871                unlink(tmptxtfile);
05872                inprocess_count(vmu->mailbox, vmu->context, -1);
05873             } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
05874                ast_debug(1, "The recorded media file is gone, so we should remove the .txt file too!\n");
05875                unlink(tmptxtfile);
05876                ast_unlock_path(dir);
05877                inprocess_count(vmu->mailbox, vmu->context, -1);
05878                if (ast_check_realtime("voicemail_data")) {
05879                   ast_destroy_realtime("voicemail_data", "filename", tmptxtfile, SENTINEL);
05880                }
05881             } else {
05882 #ifndef IMAP_STORAGE
05883                msgnum = last_message_index(vmu, dir) + 1;
05884 #endif
05885                make_file(fn, sizeof(fn), dir, msgnum);
05886 
05887                /* assign a variable with the name of the voicemail file */ 
05888 #ifndef IMAP_STORAGE
05889                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
05890 #else
05891                pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
05892 #endif
05893 
05894                snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
05895                ast_filerename(tmptxtfile, fn, NULL);
05896                rename(tmptxtfile, txtfile);
05897                inprocess_count(vmu->mailbox, vmu->context, -1);
05898 
05899                /* Properly set permissions on voicemail text descriptor file.
05900                   Unfortunately mkstemp() makes this file 0600 on most unix systems. */
05901                if (chmod(txtfile, VOICEMAIL_FILE_MODE) < 0)
05902                   ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", txtfile, strerror(errno));
05903 
05904                ast_unlock_path(dir);
05905                if (ast_check_realtime("voicemail_data")) {
05906                   snprintf(tmpdur, sizeof(tmpdur), "%d", duration);
05907                   ast_update_realtime("voicemail_data", "filename", tmptxtfile, "filename", fn, "duration", tmpdur, SENTINEL);
05908                }
05909                /* We must store the file first, before copying the message, because
05910                 * ODBC storage does the entire copy with SQL.
05911                 */
05912                if (ast_fileexists(fn, NULL, NULL) > 0) {
05913                   STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag);
05914                }
05915 
05916                /* Are there to be more recipients of this message? */
05917                while (tmpptr) {
05918                   struct ast_vm_user recipu, *recip;
05919                   char *exten, *cntx;
05920                
05921                   exten = strsep(&tmpptr, "&");
05922                   cntx = strchr(exten, '@');
05923                   if (cntx) {
05924                      *cntx = '\0';
05925                      cntx++;
05926                   }
05927                   if ((recip = find_user(&recipu, cntx, exten))) {
05928                      copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
05929                      free_user(recip);
05930                   }
05931                }
05932 #ifndef IMAP_STORAGE
05933                if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) { /* If this is an Urgent message */
05934                   /* Move the message from INBOX to Urgent folder if this is urgent! */
05935                   char sfn[PATH_MAX];
05936                   char dfn[PATH_MAX];
05937                   int x;
05938                   /* It's easier just to try to make it than to check for its existence */
05939                   create_dirpath(urgdir, sizeof(urgdir), vmu->context, ext, "Urgent");
05940                   x = last_message_index(vmu, urgdir) + 1;
05941                   make_file(sfn, sizeof(sfn), dir, msgnum);
05942                   make_file(dfn, sizeof(dfn), urgdir, x);
05943                   ast_debug(5, "Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
05944                   RENAME(dir, msgnum, vmu->mailbox, vmu->context, urgdir, x, sfn, dfn);
05945                   /* Notification must happen for this new message in Urgent folder, not INBOX */
05946                   ast_copy_string(fn, dfn, sizeof(fn));
05947                   msgnum = x;
05948                }
05949 #endif
05950                /* Notification needs to happen after the copy, though. */
05951                if (ast_fileexists(fn, NULL, NULL)) {
05952 #ifdef IMAP_STORAGE
05953                   notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
05954                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05955                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05956                      flag);
05957 #else
05958                   notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
05959                      S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
05960                      S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
05961                      flag);
05962 #endif
05963                }
05964 
05965                /* Disposal needs to happen after the optional move and copy */
05966                if (ast_fileexists(fn, NULL, NULL)) {
05967                   DISPOSE(dir, msgnum);
05968                }
05969             }
05970          }
05971       } else {
05972          inprocess_count(vmu->mailbox, vmu->context, -1);
05973       }
05974       if (res == '0') {
05975          goto transfer;
05976       } else if (res > 0 && res != 't')
05977          res = 0;
05978 
05979       if (duration < vmu->minsecs)
05980          /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
05981          pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05982       else
05983          pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
05984    } else
05985       ast_log(AST_LOG_WARNING, "No format for saving voicemail?\n");
05986 leave_vm_out:
05987    free_user(vmu);
05988 
05989 #ifdef IMAP_STORAGE
05990    /* expunge message - use UID Expunge if supported on IMAP server*/
05991    ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
05992    if (expungeonhangup == 1) {
05993       ast_mutex_lock(&vms->lock);
05994 #ifdef HAVE_IMAP_TK2006
05995       if (LEVELUIDPLUS (vms->mailstream)) {
05996          mail_expunge_full(vms->mailstream, NIL, EX_UID);
05997       } else 
05998 #endif
05999          mail_expunge(vms->mailstream);
06000       ast_mutex_unlock(&vms->lock);
06001    }
06002 #endif
06003 
06004    ast_free(tmp);
06005    return res;
06006 }

static int load_config ( int  reload  )  [static]

Definition at line 11512 of file app_voicemail_imapstorage.c.

References adsifdn, adsisec, adsiver, append_mailbox(), apply_options_full(), ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, 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_unload_realtime(), ast_variable_browse(), ast_variable_retrieve(), ASTERISK_USERNAME, callcontext, charset, cidinternalcontexts, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, 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, 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, LOG_ERROR, MAX_NUM_CID_CONTEXTS, MAXMSG, MAXMSGLIMIT, MINPASSWORD, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, pagerbody, pagerdateformat, pagerfromstring, pagersubject, populate_defaults(), PWDCHANGE_EXTERNAL, PWDCHANGE_INTERNAL, read_password_from_file(), saydurationminfo, SENDMAIL, smdi_iface, start_poll_thread(), stop_poll_thread(), strsep(), substitute_escapes(), THRESHOLD_SILENCE, 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_reenterpassword, VM_REVIEW, VM_SAYCID, VM_SAYDURATION, VM_SEARCH, VM_SKIPAFTERCMD, VM_SVMAIL, VM_TEMPGREETWARN, and VOICEMAIL_CONFIG.

11513 {
11514    struct ast_vm_user *current;
11515    struct ast_config *cfg, *ucfg;
11516    char *cat;
11517    struct ast_variable *var;
11518    const char *val;
11519    char *q, *stringp, *tmp;
11520    int x;
11521    int tmpadsi[4];
11522    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11523    char secretfn[PATH_MAX] = "";
11524 
11525    ast_unload_realtime("voicemail");
11526    ast_unload_realtime("voicemail_data");
11527 
11528    if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11529       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
11530          return 0;
11531       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
11532          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11533          ucfg = NULL;
11534       }
11535       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11536       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) == CONFIG_STATUS_FILEINVALID) {
11537          ast_config_destroy(ucfg);
11538          ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11539          return 0;
11540       }
11541    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
11542       ast_log(LOG_ERROR, "Config file " VOICEMAIL_CONFIG " is in an invalid format.  Aborting.\n");
11543       return 0;
11544    } else {
11545       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11546       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
11547          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Avoiding.\n");
11548          ucfg = NULL;
11549       }
11550    }
11551 #ifdef IMAP_STORAGE
11552    ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder));
11553 #endif
11554    /* set audio control prompts */
11555    strcpy(listen_control_forward_key, DEFAULT_LISTEN_CONTROL_FORWARD_KEY);
11556    strcpy(listen_control_reverse_key, DEFAULT_LISTEN_CONTROL_REVERSE_KEY);
11557    strcpy(listen_control_pause_key, DEFAULT_LISTEN_CONTROL_PAUSE_KEY);
11558    strcpy(listen_control_restart_key, DEFAULT_LISTEN_CONTROL_RESTART_KEY);
11559    strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);
11560 
11561    /* Free all the users structure */  
11562    free_vm_users();
11563 
11564    /* Free all the zones structure */
11565    free_vm_zones();
11566 
11567    AST_LIST_LOCK(&users);  
11568 
11569    memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
11570    memset(ext_pass_check_cmd, 0, sizeof(ext_pass_check_cmd));
11571 
11572    if (cfg) {
11573       /* General settings */
11574 
11575       if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))
11576          val = "default";
11577       ast_copy_string(userscontext, val, sizeof(userscontext));
11578       /* Attach voice message to mail message ? */
11579       if (!(val = ast_variable_retrieve(cfg, "general", "attach"))) 
11580          val = "yes";
11581       ast_set2_flag((&globalflags), ast_true(val), VM_ATTACH); 
11582 
11583       if (!(val = ast_variable_retrieve(cfg, "general", "searchcontexts")))
11584          val = "no";
11585       ast_set2_flag((&globalflags), ast_true(val), VM_SEARCH);
11586 
11587       volgain = 0.0;
11588       if ((val = ast_variable_retrieve(cfg, "general", "volgain")))
11589          sscanf(val, "%30lf", &volgain);
11590 
11591 #ifdef ODBC_STORAGE
11592       strcpy(odbc_database, "asterisk");
11593       if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
11594          ast_copy_string(odbc_database, val, sizeof(odbc_database));
11595       }
11596       strcpy(odbc_table, "voicemessages");
11597       if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) {
11598          ast_copy_string(odbc_table, val, sizeof(odbc_table));
11599       }
11600 #endif      
11601       /* Mail command */
11602       strcpy(mailcmd, SENDMAIL);
11603       if ((val = ast_variable_retrieve(cfg, "general", "mailcmd")))
11604          ast_copy_string(mailcmd, val, sizeof(mailcmd)); /* User setting */
11605 
11606       maxsilence = 0;
11607       if ((val = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
11608          maxsilence = atoi(val);
11609          if (maxsilence > 0)
11610             maxsilence *= 1000;
11611       }
11612       
11613       if (!(val = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
11614          maxmsg = MAXMSG;
11615       } else {
11616          maxmsg = atoi(val);
11617          if (maxmsg < 0) {
11618             ast_log(AST_LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", val, MAXMSG);
11619             maxmsg = MAXMSG;
11620          } else if (maxmsg > MAXMSGLIMIT) {
11621             ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11622             maxmsg = MAXMSGLIMIT;
11623          }
11624       }
11625 
11626       if (!(val = ast_variable_retrieve(cfg, "general", "backupdeleted"))) {
11627          maxdeletedmsg = 0;
11628       } else {
11629          if (sscanf(val, "%30d", &x) == 1)
11630             maxdeletedmsg = x;
11631          else if (ast_true(val))
11632             maxdeletedmsg = MAXMSG;
11633          else
11634             maxdeletedmsg = 0;
11635 
11636          if (maxdeletedmsg < 0) {
11637             ast_log(AST_LOG_WARNING, "Invalid number of deleted messages saved per mailbox '%s'. Using default value %i\n", val, MAXMSG);
11638             maxdeletedmsg = MAXMSG;
11639          } else if (maxdeletedmsg > MAXMSGLIMIT) {
11640             ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, val);
11641             maxdeletedmsg = MAXMSGLIMIT;
11642          }
11643       }
11644 
11645       /* Load date format config for voicemail mail */
11646       if ((val = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
11647          ast_copy_string(emaildateformat, val, sizeof(emaildateformat));
11648       }
11649 
11650       /* Load date format config for voicemail pager mail */
11651       if ((val = ast_variable_retrieve(cfg, "general", "pagerdateformat"))) {
11652          ast_copy_string(pagerdateformat, val, sizeof(pagerdateformat));
11653       }
11654 
11655       /* External password changing command */
11656       if ((val = ast_variable_retrieve(cfg, "general", "externpass"))) {
11657          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
11658          pwdchange = PWDCHANGE_EXTERNAL;
11659       } else if ((val = ast_variable_retrieve(cfg, "general", "externpassnotify"))) {
11660          ast_copy_string(ext_pass_cmd, val, sizeof(ext_pass_cmd));
11661          pwdchange = PWDCHANGE_EXTERNAL | PWDCHANGE_INTERNAL;
11662       }
11663  
11664       /* External password validation command */
11665       if ((val = ast_variable_retrieve(cfg, "general", "externpasscheck"))) {
11666          ast_copy_string(ext_pass_check_cmd, val, sizeof(ext_pass_check_cmd));
11667          ast_log(AST_LOG_DEBUG, "found externpasscheck: %s\n", ext_pass_check_cmd);
11668       }
11669 
11670 #ifdef IMAP_STORAGE
11671       /* IMAP server address */
11672       if ((val = ast_variable_retrieve(cfg, "general", "imapserver"))) {
11673          ast_copy_string(imapserver, val, sizeof(imapserver));
11674       } else {
11675          ast_copy_string(imapserver, "localhost", sizeof(imapserver));
11676       }
11677       /* IMAP server port */
11678       if ((val = ast_variable_retrieve(cfg, "general", "imapport"))) {
11679          ast_copy_string(imapport, val, sizeof(imapport));
11680       } else {
11681          ast_copy_string(imapport, "143", sizeof(imapport));
11682       }
11683       /* IMAP server flags */
11684       if ((val = ast_variable_retrieve(cfg, "general", "imapflags"))) {
11685          ast_copy_string(imapflags, val, sizeof(imapflags));
11686       }
11687       /* IMAP server master username */
11688       if ((val = ast_variable_retrieve(cfg, "general", "authuser"))) {
11689          ast_copy_string(authuser, val, sizeof(authuser));
11690       }
11691       /* IMAP server master password */
11692       if ((val = ast_variable_retrieve(cfg, "general", "authpassword"))) {
11693          ast_copy_string(authpassword, val, sizeof(authpassword));
11694       }
11695       /* Expunge on exit */
11696       if ((val = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
11697          if (ast_false(val))
11698             expungeonhangup = 0;
11699          else
11700             expungeonhangup = 1;
11701       } else {
11702          expungeonhangup = 1;
11703       }
11704       /* IMAP voicemail folder */
11705       if ((val = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
11706          ast_copy_string(imapfolder, val, sizeof(imapfolder));
11707       } else {
11708          ast_copy_string(imapfolder, "INBOX", sizeof(imapfolder));
11709       }
11710       if ((val = ast_variable_retrieve(cfg, "general", "imapparentfolder"))) {
11711          ast_copy_string(imapparentfolder, val, sizeof(imapparentfolder));
11712       }
11713       if ((val = ast_variable_retrieve(cfg, "general", "imapgreetings"))) {
11714          imapgreetings = ast_true(val);
11715       } else {
11716          imapgreetings = 0;
11717       }
11718       if ((val = ast_variable_retrieve(cfg, "general", "greetingfolder"))) {
11719          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
11720       } else if ((val = ast_variable_retrieve(cfg, "general", "greetingsfolder"))) {
11721          /* Also support greetingsfolder as documented in voicemail.conf.sample */
11722          ast_copy_string(greetingfolder, val, sizeof(greetingfolder));
11723       } else {
11724          ast_copy_string(greetingfolder, imapfolder, sizeof(greetingfolder));
11725       }
11726 
11727       /* There is some very unorthodox casting done here. This is due
11728        * to the way c-client handles the argument passed in. It expects a 
11729        * void pointer and casts the pointer directly to a long without
11730        * first dereferencing it. */
11731       if ((val = ast_variable_retrieve(cfg, "general", "imapreadtimeout"))) {
11732          mail_parameters(NIL, SET_READTIMEOUT, (void *) (atol(val)));
11733       } else {
11734          mail_parameters(NIL, SET_READTIMEOUT, (void *) 60L);
11735       }
11736 
11737       if ((val = ast_variable_retrieve(cfg, "general", "imapwritetimeout"))) {
11738          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) (atol(val)));
11739       } else {
11740          mail_parameters(NIL, SET_WRITETIMEOUT, (void *) 60L);
11741       }
11742 
11743       if ((val = ast_variable_retrieve(cfg, "general", "imapopentimeout"))) {
11744          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) (atol(val)));
11745       } else {
11746          mail_parameters(NIL, SET_OPENTIMEOUT, (void *) 60L);
11747       }
11748 
11749       if ((val = ast_variable_retrieve(cfg, "general", "imapclosetimeout"))) {
11750          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) (atol(val)));
11751       } else {
11752          mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) 60L);
11753       }
11754 
11755       /* Increment configuration version */
11756       imapversion++;
11757 #endif
11758       /* External voicemail notify application */
11759       if ((val = ast_variable_retrieve(cfg, "general", "externnotify"))) {
11760          ast_copy_string(externnotify, val, sizeof(externnotify));
11761          ast_debug(1, "found externnotify: %s\n", externnotify);
11762       } else {
11763          externnotify[0] = '\0';
11764       }
11765 
11766       /* SMDI voicemail notification */
11767       if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
11768          ast_debug(1, "Enabled SMDI voicemail notification\n");
11769          if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
11770             smdi_iface = ast_smdi_interface_find(val);
11771          } else {
11772             ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
11773             smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
11774          }
11775          if (!smdi_iface) {
11776             ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
11777          } 
11778       }
11779 
11780       /* Silence treshold */
11781       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
11782       if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
11783          silencethreshold = atoi(val);
11784       
11785       if (!(val = ast_variable_retrieve(cfg, "general", "serveremail"))) 
11786          val = ASTERISK_USERNAME;
11787       ast_copy_string(serveremail, val, sizeof(serveremail));
11788       
11789       vmmaxsecs = 0;
11790       if ((val = ast_variable_retrieve(cfg, "general", "maxsecs"))) {
11791          if (sscanf(val, "%30d", &x) == 1) {
11792             vmmaxsecs = x;
11793          } else {
11794             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
11795          }
11796       } else if ((val = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
11797          static int maxmessage_deprecate = 0;
11798          if (maxmessage_deprecate == 0) {
11799             maxmessage_deprecate = 1;
11800             ast_log(AST_LOG_WARNING, "Setting 'maxmessage' has been deprecated in favor of 'maxsecs'.\n");
11801          }
11802          if (sscanf(val, "%30d", &x) == 1) {
11803             vmmaxsecs = x;
11804          } else {
11805             ast_log(AST_LOG_WARNING, "Invalid max message time length\n");
11806          }
11807       }
11808 
11809       vmminsecs = 0;
11810       if ((val = ast_variable_retrieve(cfg, "general", "minsecs"))) {
11811          if (sscanf(val, "%30d", &x) == 1) {
11812             vmminsecs = x;
11813             if (maxsilence / 1000 >= vmminsecs) {
11814                ast_log(AST_LOG_WARNING, "maxsilence should be less than minsecs or you may get empty messages\n");
11815             }
11816          } else {
11817             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
11818          }
11819       } else if ((val = ast_variable_retrieve(cfg, "general", "minmessage"))) {
11820          static int maxmessage_deprecate = 0;
11821          if (maxmessage_deprecate == 0) {
11822             maxmessage_deprecate = 1;
11823             ast_log(AST_LOG_WARNING, "Setting 'minmessage' has been deprecated in favor of 'minsecs'.\n");
11824          }
11825          if (sscanf(val, "%30d", &x) == 1) {
11826             vmminsecs = x;
11827             if (maxsilence / 1000 >= vmminsecs) {
11828                ast_log(AST_LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
11829             }
11830          } else {
11831             ast_log(AST_LOG_WARNING, "Invalid min message time length\n");
11832          }
11833       }
11834 
11835       val = ast_variable_retrieve(cfg, "general", "format");
11836       if (!val) {
11837          val = "wav";   
11838       } else {
11839          tmp = ast_strdupa(val);
11840          val = ast_format_str_reduce(tmp);
11841          if (!val) {
11842             ast_log(LOG_ERROR, "Error processing format string, defaulting to format 'wav'\n");
11843             val = "wav";
11844          }
11845       }
11846       ast_copy_string(vmfmts, val, sizeof(vmfmts));
11847 
11848       skipms = 3000;
11849       if ((val = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
11850          if (sscanf(val, "%30d", &x) == 1) {
11851             maxgreet = x;
11852          } else {
11853             ast_log(AST_LOG_WARNING, "Invalid max message greeting length\n");
11854          }
11855       }
11856 
11857       if ((val = ast_variable_retrieve(cfg, "general", "skipms"))) {
11858          if (sscanf(val, "%30d", &x) == 1) {
11859             skipms = x;
11860          } else {
11861             ast_log(AST_LOG_WARNING, "Invalid skipms value\n");
11862          }
11863       }
11864 
11865       maxlogins = 3;
11866       if ((val = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
11867          if (sscanf(val, "%30d", &x) == 1) {
11868             maxlogins = x;
11869          } else {
11870             ast_log(AST_LOG_WARNING, "Invalid max failed login attempts\n");
11871          }
11872       }
11873 
11874       minpassword = MINPASSWORD;
11875       if ((val = ast_variable_retrieve(cfg, "general", "minpassword"))) {
11876          if (sscanf(val, "%30d", &x) == 1) {
11877             minpassword = x;
11878          } else {
11879             ast_log(AST_LOG_WARNING, "Invalid minimum password length.  Default to %d\n", minpassword);
11880          }
11881       }
11882 
11883       /* Force new user to record name ? */
11884       if (!(val = ast_variable_retrieve(cfg, "general", "forcename"))) 
11885          val = "no";
11886       ast_set2_flag((&globalflags), ast_true(val), VM_FORCENAME);
11887 
11888       /* Force new user to record greetings ? */
11889       if (!(val = ast_variable_retrieve(cfg, "general", "forcegreetings"))) 
11890          val = "no";
11891       ast_set2_flag((&globalflags), ast_true(val), VM_FORCEGREET);
11892 
11893       if ((val = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))) {
11894          ast_debug(1, "VM_CID Internal context string: %s\n", val);
11895          stringp = ast_strdupa(val);
11896          for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
11897             if (!ast_strlen_zero(stringp)) {
11898                q = strsep(&stringp, ",");
11899                while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
11900                   q++;
11901                ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
11902                ast_debug(1, "VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
11903             } else {
11904                cidinternalcontexts[x][0] = '\0';
11905             }
11906          }
11907       }
11908       if (!(val = ast_variable_retrieve(cfg, "general", "review"))){
11909          ast_debug(1, "VM Review Option disabled globally\n");
11910          val = "no";
11911       }
11912       ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW); 
11913 
11914       /* Temporary greeting reminder */
11915       if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
11916          ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n");
11917          val = "no";
11918       } else {
11919          ast_debug(1, "VM Temporary Greeting Reminder Option enabled globally\n");
11920       }
11921       ast_set2_flag((&globalflags), ast_true(val), VM_TEMPGREETWARN);
11922       if (!(val = ast_variable_retrieve(cfg, "general", "messagewrap"))){
11923          ast_debug(1, "VM next message wrap disabled globally\n");
11924          val = "no";
11925       }
11926       ast_set2_flag((&globalflags), ast_true(val), VM_MESSAGEWRAP);  
11927 
11928       if (!(val = ast_variable_retrieve(cfg, "general", "operator"))){
11929          ast_debug(1, "VM Operator break disabled globally\n");
11930          val = "no";
11931       }
11932       ast_set2_flag((&globalflags), ast_true(val), VM_OPERATOR);  
11933 
11934       if (!(val = ast_variable_retrieve(cfg, "general", "saycid"))) {
11935          ast_debug(1, "VM CID Info before msg disabled globally\n");
11936          val = "no";
11937       } 
11938       ast_set2_flag((&globalflags), ast_true(val), VM_SAYCID); 
11939 
11940       if (!(val = ast_variable_retrieve(cfg, "general", "sendvoicemail"))){
11941          ast_debug(1, "Send Voicemail msg disabled globally\n");
11942          val = "no";
11943       }
11944       ast_set2_flag((&globalflags), ast_true(val), VM_SVMAIL);
11945    
11946       if (!(val = ast_variable_retrieve(cfg, "general", "envelope"))) {
11947          ast_debug(1, "ENVELOPE before msg enabled globally\n");
11948          val = "yes";
11949       }
11950       ast_set2_flag((&globalflags), ast_true(val), VM_ENVELOPE);  
11951 
11952       if (!(val = ast_variable_retrieve(cfg, "general", "moveheard"))) {
11953          ast_debug(1, "Move Heard enabled globally\n");
11954          val = "yes";
11955       }
11956       ast_set2_flag((&globalflags), ast_true(val), VM_MOVEHEARD); 
11957 
11958       if (!(val = ast_variable_retrieve(cfg, "general", "forward_urgent_auto"))) {
11959          ast_debug(1, "Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
11960          val = "no";
11961       }
11962       ast_set2_flag((&globalflags), ast_true(val), VM_FWDURGAUTO);   
11963 
11964       if (!(val = ast_variable_retrieve(cfg, "general", "sayduration"))) {
11965          ast_debug(1, "Duration info before msg enabled globally\n");
11966          val = "yes";
11967       }
11968       ast_set2_flag((&globalflags), ast_true(val), VM_SAYDURATION);  
11969 
11970       saydurationminfo = 2;
11971       if ((val = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
11972          if (sscanf(val, "%30d", &x) == 1) {
11973             saydurationminfo = x;
11974          } else {
11975             ast_log(AST_LOG_WARNING, "Invalid min duration for say duration\n");
11976          }
11977       }
11978 
11979       if (!(val = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
11980          ast_debug(1, "We are not going to skip to the next msg after save/delete\n");
11981          val = "no";
11982       }
11983       ast_set2_flag((&globalflags), ast_true(val), VM_SKIPAFTERCMD);
11984 
11985       if ((val = ast_variable_retrieve(cfg, "general", "dialout"))) {
11986          ast_copy_string(dialcontext, val, sizeof(dialcontext));
11987          ast_debug(1, "found dialout context: %s\n", dialcontext);
11988       } else {
11989          dialcontext[0] = '\0';  
11990       }
11991       
11992       if ((val = ast_variable_retrieve(cfg, "general", "callback"))) {
11993          ast_copy_string(callcontext, val, sizeof(callcontext));
11994          ast_debug(1, "found callback context: %s\n", callcontext);
11995       } else {
11996          callcontext[0] = '\0';
11997       }
11998 
11999       if ((val = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
12000          ast_copy_string(exitcontext, val, sizeof(exitcontext));
12001          ast_debug(1, "found operator context: %s\n", exitcontext);
12002       } else {
12003          exitcontext[0] = '\0';
12004       }
12005       
12006       /* load password sounds configuration */
12007       if ((val = ast_variable_retrieve(cfg, "general", "vm-password")))
12008          ast_copy_string(vm_password, val, sizeof(vm_password));
12009       if ((val = ast_variable_retrieve(cfg, "general", "vm-newpassword")))
12010          ast_copy_string(vm_newpassword, val, sizeof(vm_newpassword));
12011       if ((val = ast_variable_retrieve(cfg, "general", "vm-invalid-password")))
12012          ast_copy_string(vm_invalid_password, val, sizeof(vm_invalid_password));
12013       if ((val = ast_variable_retrieve(cfg, "general", "vm-passchanged")))
12014          ast_copy_string(vm_passchanged, val, sizeof(vm_passchanged));
12015       if ((val = ast_variable_retrieve(cfg, "general", "vm-reenterpassword")))
12016          ast_copy_string(vm_reenterpassword, val, sizeof(vm_reenterpassword));
12017       if ((val = ast_variable_retrieve(cfg, "general", "vm-mismatch")))
12018          ast_copy_string(vm_mismatch, val, sizeof(vm_mismatch));
12019       if ((val = ast_variable_retrieve(cfg, "general", "vm-pls-try-again"))) {
12020          ast_copy_string(vm_pls_try_again, val, sizeof(vm_pls_try_again));
12021       }
12022       /* load configurable audio prompts */
12023       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-forward-key")) && is_valid_dtmf(val))
12024          ast_copy_string(listen_control_forward_key, val, sizeof(listen_control_forward_key));
12025       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-reverse-key")) && is_valid_dtmf(val))
12026          ast_copy_string(listen_control_reverse_key, val, sizeof(listen_control_reverse_key));
12027       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-pause-key")) && is_valid_dtmf(val))
12028          ast_copy_string(listen_control_pause_key, val, sizeof(listen_control_pause_key));
12029       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-restart-key")) && is_valid_dtmf(val))
12030          ast_copy_string(listen_control_restart_key, val, sizeof(listen_control_restart_key));
12031       if ((val = ast_variable_retrieve(cfg, "general", "listen-control-stop-key")) && is_valid_dtmf(val))
12032          ast_copy_string(listen_control_stop_key, val, sizeof(listen_control_stop_key));
12033 
12034       if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory"))) 
12035          val = "no";
12036       ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD); 
12037 
12038       if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
12039          val = "voicemail.conf";
12040       }
12041       if (!(strcmp(val, "spooldir"))) {
12042          passwordlocation = OPT_PWLOC_SPOOLDIR;
12043       } else {
12044          passwordlocation = OPT_PWLOC_VOICEMAILCONF;
12045       }
12046 
12047       poll_freq = DEFAULT_POLL_FREQ;
12048       if ((val = ast_variable_retrieve(cfg, "general", "pollfreq"))) {
12049          if (sscanf(val, "%30u", &poll_freq) != 1) {
12050             poll_freq = DEFAULT_POLL_FREQ;
12051             ast_log(AST_LOG_ERROR, "'%s' is not a valid value for the pollfreq option!\n", val);
12052          }
12053       }
12054 
12055       poll_mailboxes = 0;
12056       if ((val = ast_variable_retrieve(cfg, "general", "pollmailboxes")))
12057          poll_mailboxes = ast_true(val);
12058 
12059       if (ucfg) { 
12060          for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
12061             if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
12062                continue;
12063             if ((current = find_or_create(userscontext, cat))) {
12064                populate_defaults(current);
12065                apply_options_full(current, ast_variable_browse(ucfg, cat));
12066                ast_copy_string(current->context, userscontext, sizeof(current->context));
12067                if (!ast_strlen_zero(current->password) && current->passwordlocation == OPT_PWLOC_VOICEMAILCONF) {
12068                   current->passwordlocation = OPT_PWLOC_USERSCONF;
12069                }
12070 
12071                switch (current->passwordlocation) {
12072                case OPT_PWLOC_SPOOLDIR:
12073                   snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, current->context, current->mailbox);
12074                   read_password_from_file(secretfn, current->password, sizeof(current->password));
12075                }
12076             }
12077          }
12078          ast_config_destroy(ucfg);
12079       }
12080       cat = ast_category_browse(cfg, NULL);
12081       while (cat) {
12082          if (strcasecmp(cat, "general")) {
12083             var = ast_variable_browse(cfg, cat);
12084             if (strcasecmp(cat, "zonemessages")) {
12085                /* Process mailboxes in this context */
12086                while (var) {
12087                   append_mailbox(cat, var->name, var->value);
12088                   var = var->next;
12089                }
12090             } else {
12091                /* Timezones in this context */
12092                while (var) {
12093                   struct vm_zone *z;
12094                   if ((z = ast_malloc(sizeof(*z)))) {
12095                      char *msg_format, *tzone;
12096                      msg_format = ast_strdupa(var->value);
12097                      tzone = strsep(&msg_format, "|,");
12098                      if (msg_format) {
12099                         ast_copy_string(z->name, var->name, sizeof(z->name));
12100                         ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
12101                         ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
12102                         AST_LIST_LOCK(&zones);
12103                         AST_LIST_INSERT_HEAD(&zones, z, list);
12104                         AST_LIST_UNLOCK(&zones);
12105                      } else {
12106                         ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
12107                         ast_free(z);
12108                      }
12109                   } else {
12110                      AST_LIST_UNLOCK(&users);
12111                      ast_config_destroy(cfg);
12112                      return -1;
12113                   }
12114                   var = var->next;
12115                }
12116             }
12117          }
12118          cat = ast_category_browse(cfg, cat);
12119       }
12120       memset(fromstring, 0, sizeof(fromstring));
12121       memset(pagerfromstring, 0, sizeof(pagerfromstring));
12122       strcpy(charset, "ISO-8859-1");
12123       if (emailbody) {
12124          ast_free(emailbody);
12125          emailbody = NULL;
12126       }
12127       if (emailsubject) {
12128          ast_free(emailsubject);
12129          emailsubject = NULL;
12130       }
12131       if (pagerbody) {
12132          ast_free(pagerbody);
12133          pagerbody = NULL;
12134       }
12135       if (pagersubject) {
12136          ast_free(pagersubject);
12137          pagersubject = NULL;
12138       }
12139       if ((val = ast_variable_retrieve(cfg, "general", "pbxskip")))
12140          ast_set2_flag((&globalflags), ast_true(val), VM_PBXSKIP);
12141       if ((val = ast_variable_retrieve(cfg, "general", "fromstring")))
12142          ast_copy_string(fromstring, val, sizeof(fromstring));
12143       if ((val = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
12144          ast_copy_string(pagerfromstring, val, sizeof(pagerfromstring));
12145       if ((val = ast_variable_retrieve(cfg, "general", "charset")))
12146          ast_copy_string(charset, val, sizeof(charset));
12147       if ((val = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
12148          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12149          for (x = 0; x < 4; x++) {
12150             memcpy(&adsifdn[x], &tmpadsi[x], 1);
12151          }
12152       }
12153       if ((val = ast_variable_retrieve(cfg, "general", "adsisec"))) {
12154          sscanf(val, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12155          for (x = 0; x < 4; x++) {
12156             memcpy(&adsisec[x], &tmpadsi[x], 1);
12157          }
12158       }
12159       if ((val = ast_variable_retrieve(cfg, "general", "adsiver"))) {
12160          if (atoi(val)) {
12161             adsiver = atoi(val);
12162          }
12163       }
12164       if ((val = ast_variable_retrieve(cfg, "general", "tz"))) {
12165          ast_copy_string(zonetag, val, sizeof(zonetag));
12166       }
12167       if ((val = ast_variable_retrieve(cfg, "general", "locale"))) {
12168          ast_copy_string(locale, val, sizeof(locale));
12169       }
12170       if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
12171          emailsubject = ast_strdup(val);
12172       }
12173       if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
12174          emailbody = ast_strdup(substitute_escapes(val));
12175       }
12176       if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
12177          pagersubject = ast_strdup(val);
12178       }
12179       if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
12180          pagerbody = ast_strdup(substitute_escapes(val));
12181       }
12182       AST_LIST_UNLOCK(&users);
12183       ast_config_destroy(cfg);
12184 
12185       if (poll_mailboxes && poll_thread == AST_PTHREADT_NULL)
12186          start_poll_thread();
12187       if (!poll_mailboxes && poll_thread != AST_PTHREADT_NULL)
12188          stop_poll_thread();;
12189 
12190       return 0;
12191    } else {
12192       AST_LIST_UNLOCK(&users);
12193       ast_log(AST_LOG_WARNING, "Failed to load configuration file.\n");
12194       if (ucfg)
12195          ast_config_destroy(ucfg);
12196       return 0;
12197    }
12198 }

static int load_module ( void   )  [static]

Definition at line 12690 of file app_voicemail_imapstorage.c.

References ao2_container_alloc, 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, RQ_CHAR, RQ_UINTEGER3, sayname(), SENTINEL, vm_box_exists(), vm_data_providers, vm_exec(), vm_execmain(), vmauthenticate(), and vmsayname_exec().

12691 {
12692    int res;
12693    my_umask = umask(0);
12694    umask(my_umask);
12695 
12696    if (!(inprocess_container = ao2_container_alloc(573, inprocess_hash_fn, inprocess_cmp_fn))) {
12697       return AST_MODULE_LOAD_DECLINE;
12698    }
12699 
12700    /* compute the location of the voicemail spool directory */
12701    snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
12702    
12703    if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
12704       ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor.  MWI will not work\n");
12705    }
12706 
12707    if ((res = load_config(0)))
12708       return res;
12709 
12710    res = ast_register_application_xml(app, vm_exec);
12711    res |= ast_register_application_xml(app2, vm_execmain);
12712    res |= ast_register_application_xml(app3, vm_box_exists);
12713    res |= ast_register_application_xml(app4, vmauthenticate);
12714    res |= ast_register_application_xml(sayname_app, vmsayname_exec);
12715    res |= ast_custom_function_register(&mailbox_exists_acf);
12716    res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
12717 #ifdef TEST_FRAMEWORK
12718    res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
12719    res |= AST_TEST_REGISTER(test_voicemail_msgcount);
12720    res |= AST_TEST_REGISTER(test_voicemail_vmuser);
12721    res |= AST_TEST_REGISTER(test_voicemail_notify_endl);
12722 #endif
12723 
12724    if (res)
12725       return res;
12726 
12727    ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
12728    ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));
12729 
12730    ast_install_vm_functions(has_voicemail, inboxcount, inboxcount2, messagecount, sayname);
12731    ast_realtime_require_field("voicemail", "uniqueid", RQ_UINTEGER3, 11, "password", RQ_CHAR, 10, SENTINEL);
12732    ast_realtime_require_field("voicemail_data", "filename", RQ_CHAR, 30, "duration", RQ_UINTEGER3, 5, SENTINEL);
12733 
12734    return res;
12735 }

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

01564 {
01565    return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
01566 }

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

References add_email_attachment(), ast_channel_release(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_localtime(), ast_log(), ast_random(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strftime_locale(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), charset, check_mime(), CONFIG_FLAG_NOCACHE, config_flags, ast_vm_user::context, ast_vm_user::email, ast_vm_user::emailbody, emailbody, emaildateformat, ast_vm_user::emailsubject, emailsubject, ENDL, fromstring, ast_vm_user::fullname, globalflags, ast_vm_user::locale, ast_vm_user::mailbox, make_dir(), make_file(), MAXHOSTNAMELEN, ast_channel::name, prep_email_sub_vars(), ast_channel::priority, S_OR, strip_control_and_high(), VM_PBXSKIP, and vmu_tm().

04395 {
04396    char date[256];
04397    char host[MAXHOSTNAMELEN] = "";
04398    char who[256];
04399    char bound[256];
04400    char dur[256];
04401    struct ast_tm tm;
04402    char enc_cidnum[256] = "", enc_cidname[256] = "";
04403    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04404    char *greeting_attachment; 
04405    char filename[256];
04406 
04407    if (!str1 || !str2) {
04408       ast_free(str1);
04409       ast_free(str2);
04410       return;
04411    }
04412 
04413    if (cidnum) {
04414       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04415    }
04416    if (cidname) {
04417       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04418    }
04419    gethostname(host, sizeof(host) - 1);
04420 
04421    if (strchr(srcemail, '@')) {
04422       ast_copy_string(who, srcemail, sizeof(who));
04423    } else {
04424       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04425    }
04426 
04427    greeting_attachment = strrchr(ast_strdupa(attach), '/');
04428    if (greeting_attachment) {
04429       *greeting_attachment++ = '\0';
04430    }
04431 
04432    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04433    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04434    fprintf(p, "Date: %s" ENDL, date);
04435 
04436    /* Set date format for voicemail mail */
04437    ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04438 
04439    if (!ast_strlen_zero(fromstring)) {
04440       struct ast_channel *ast;
04441       if ((ast = ast_dummy_channel_alloc())) {
04442          char *ptr;
04443          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04444          ast_str_substitute_variables(&str1, 0, ast, fromstring);
04445 
04446          if (check_mime(ast_str_buffer(str1))) {
04447             int first_line = 1;
04448             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04449             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04450                *ptr = '\0';
04451                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04452                first_line = 0;
04453                /* Substring is smaller, so this will never grow */
04454                ast_str_set(&str2, 0, "%s", ptr + 1);
04455             }
04456             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04457          } else {
04458             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04459          }
04460          ast = ast_channel_release(ast);
04461       } else {
04462          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04463       }
04464    } else {
04465       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04466    }
04467 
04468    if (check_mime(vmu->fullname)) {
04469       int first_line = 1;
04470       char *ptr;
04471       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(vmu->email) + 3);
04472       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04473          *ptr = '\0';
04474          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04475          first_line = 0;
04476          /* Substring is smaller, so this will never grow */
04477          ast_str_set(&str2, 0, "%s", ptr + 1);
04478       }
04479       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), vmu->email);
04480    } else {
04481       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), vmu->email);
04482    }
04483 
04484    if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
04485       char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
04486       struct ast_channel *ast;
04487       if ((ast = ast_dummy_channel_alloc())) {
04488          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04489          ast_str_substitute_variables(&str1, 0, ast, e_subj);
04490          if (check_mime(ast_str_buffer(str1))) {
04491             int first_line = 1;
04492             char *ptr;
04493             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04494             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04495                *ptr = '\0';
04496                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04497                first_line = 0;
04498                /* Substring is smaller, so this will never grow */
04499                ast_str_set(&str2, 0, "%s", ptr + 1);
04500             }
04501             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04502          } else {
04503             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04504          }
04505          ast = ast_channel_release(ast);
04506       } else {
04507          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04508       }
04509    } else if (ast_test_flag((&globalflags), VM_PBXSKIP)) {
04510       if (ast_strlen_zero(flag)) {
04511          fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04512       } else {
04513          fprintf(p, "Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04514       }
04515    } else {
04516       if (ast_strlen_zero(flag)) {
04517          fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
04518       } else {
04519          fprintf(p, "Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
04520       }
04521    }
04522 
04523    fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1,
04524       (unsigned int) ast_random(), mailbox, (int) getpid(), host);
04525    if (imap) {
04526       /* additional information needed for IMAP searching */
04527       fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
04528       /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s" ENDL, ext); */
04529       fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
04530       fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
04531 #ifdef IMAP_STORAGE
04532       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, (!ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
04533 #else
04534       fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
04535 #endif
04536       /* flag added for Urgent */
04537       fprintf(p, "X-Asterisk-VM-Flag: %s" ENDL, flag);
04538       fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
04539       fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
04540       fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
04541       fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
04542       fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
04543       if (!ast_strlen_zero(category)) {
04544          fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
04545       } else {
04546          fprintf(p, "X-Asterisk-VM-Category: " ENDL);
04547       }
04548       fprintf(p, "X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ? "Message" : greeting_attachment);
04549       fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
04550       fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long) time(NULL));
04551    }
04552    if (!ast_strlen_zero(cidnum)) {
04553       fprintf(p, "X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
04554    }
04555    if (!ast_strlen_zero(cidname)) {
04556       fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
04557    }
04558    fprintf(p, "MIME-Version: 1.0" ENDL);
04559    if (attach_user_voicemail) {
04560       /* Something unique. */
04561       snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox,
04562          (int) getpid(), (unsigned int) ast_random());
04563 
04564       fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
04565       fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
04566       fprintf(p, "--%s" ENDL, bound);
04567    }
04568    fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
04569    if (emailbody || vmu->emailbody) {
04570       char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
04571       struct ast_channel *ast;
04572       if ((ast = ast_dummy_channel_alloc())) {
04573          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04574          ast_str_substitute_variables(&str1, 0, ast, e_body);
04575 #ifdef IMAP_STORAGE
04576             {
04577                /* Convert body to native line terminators for IMAP backend */
04578                char *line = ast_str_buffer(str1), *next;
04579                do {
04580                   /* Terminate line before outputting it to the file */
04581                   if ((next = strchr(line, '\n'))) {
04582                      *next++ = '\0';
04583                   }
04584                   fprintf(p, "%s" ENDL, line);
04585                   line = next;
04586                } while (!ast_strlen_zero(line));
04587             }
04588 #else
04589          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
04590 #endif
04591          ast = ast_channel_release(ast);
04592       } else {
04593          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04594       }
04595    } else if (msgnum > -1) {
04596       if (strcmp(vmu->mailbox, mailbox)) {
04597          /* Forwarded type */
04598          struct ast_config *msg_cfg;
04599          const char *v;
04600          int inttime;
04601          char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
04602          struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04603          /* Retrieve info from VM attribute file */
04604          make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04605          make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
04606          if (strlen(fromfile) < sizeof(fromfile) - 5) {
04607             strcat(fromfile, ".txt");
04608          }
04609          if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
04610             if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04611                ast_copy_string(origcallerid, v, sizeof(origcallerid));
04612             }
04613 
04614             /* You might be tempted to do origdate, except that a) it's in the wrong
04615              * format, and b) it's missing for IMAP recordings. */
04616             if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) {
04617                struct timeval tv = { inttime, };
04618                struct ast_tm tm;
04619                ast_localtime(&tv, &tm, NULL);
04620                ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04621             }
04622             fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
04623                " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
04624                "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
04625                " chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
04626                msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
04627                date, origcallerid, origdate);
04628             ast_config_destroy(msg_cfg);
04629          } else {
04630             goto plain_message;
04631          }
04632       } else {
04633 plain_message:
04634          fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
04635             "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
04636             "want to check it when you get a chance.  Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
04637             ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
04638             (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
04639       }
04640    } else {
04641       fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
04642             "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
04643    }
04644 
04645    if (imap || attach_user_voicemail) {
04646       if (!ast_strlen_zero(attach2)) {
04647          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04648          ast_debug(5, "creating second attachment filename %s\n", filename);
04649          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
04650          snprintf(filename, sizeof(filename), "msgintro%04d.%s", msgnum, format);
04651          ast_debug(5, "creating attachment filename %s\n", filename);
04652          add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04653       } else {
04654          snprintf(filename, sizeof(filename), "msg%04d.%s", msgnum, format);
04655          ast_debug(5, "creating attachment filename %s, no second attachment.\n", filename);
04656          add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
04657       }
04658    }
04659    ast_free(str1);
04660    ast_free(str2);
04661 }

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

01581 {
01582    return snprintf(dest, len, "%s/msg%04d", dir, num);
01583 }

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

Manager list voicemail users command.

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

11347 {
11348    struct ast_vm_user *vmu = NULL;
11349    const char *id = astman_get_header(m, "ActionID");
11350    char actionid[128] = "";
11351 
11352    if (!ast_strlen_zero(id))
11353       snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
11354 
11355    AST_LIST_LOCK(&users);
11356 
11357    if (AST_LIST_EMPTY(&users)) {
11358       astman_send_ack(s, m, "There are no voicemail users currently defined.");
11359       AST_LIST_UNLOCK(&users);
11360       return RESULT_SUCCESS;
11361    }
11362    
11363    astman_send_ack(s, m, "Voicemail user list will follow");
11364    
11365    AST_LIST_TRAVERSE(&users, vmu, list) {
11366       char dirname[256];
11367 
11368 #ifdef IMAP_STORAGE
11369       int new, old;
11370       inboxcount(vmu->mailbox, &new, &old);
11371 #endif
11372       
11373       make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
11374       astman_append(s,
11375          "%s"
11376          "Event: VoicemailUserEntry\r\n"
11377          "VMContext: %s\r\n"
11378          "VoiceMailbox: %s\r\n"
11379          "Fullname: %s\r\n"
11380          "Email: %s\r\n"
11381          "Pager: %s\r\n"
11382          "ServerEmail: %s\r\n"
11383          "MailCommand: %s\r\n"
11384          "Language: %s\r\n"
11385          "TimeZone: %s\r\n"
11386          "Callback: %s\r\n"
11387          "Dialout: %s\r\n"
11388          "UniqueID: %s\r\n"
11389          "ExitContext: %s\r\n"
11390          "SayDurationMinimum: %d\r\n"
11391          "SayEnvelope: %s\r\n"
11392          "SayCID: %s\r\n"
11393          "AttachMessage: %s\r\n"
11394          "AttachmentFormat: %s\r\n"
11395          "DeleteMessage: %s\r\n"
11396          "VolumeGain: %.2f\r\n"
11397          "CanReview: %s\r\n"
11398          "CallOperator: %s\r\n"
11399          "MaxMessageCount: %d\r\n"
11400          "MaxMessageLength: %d\r\n"
11401          "NewMessageCount: %d\r\n"
11402 #ifdef IMAP_STORAGE
11403          "OldMessageCount: %d\r\n"
11404          "IMAPUser: %s\r\n"
11405 #endif
11406          "\r\n",
11407          actionid,
11408          vmu->context,
11409          vmu->mailbox,
11410          vmu->fullname,
11411          vmu->email,
11412          vmu->pager,
11413          vmu->serveremail,
11414          vmu->mailcmd,
11415          vmu->language,
11416          vmu->zonetag,
11417          vmu->callback,
11418          vmu->dialout,
11419          vmu->uniqueid,
11420          vmu->exit,
11421          vmu->saydurationm,
11422          ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
11423          ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
11424          ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
11425          vmu->attachfmt,
11426          ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
11427          vmu->volgain,
11428          ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
11429          ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
11430          vmu->maxmsg,
11431          vmu->maxsecs,
11432 #ifdef IMAP_STORAGE
11433          new, old, vmu->imapuser
11434 #else
11435          count_messages(vmu, dirname)
11436 #endif
11437          );
11438    }     
11439    astman_append(s, "Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11440 
11441    AST_LIST_UNLOCK(&users);
11442 
11443    return RESULT_SUCCESS;
11444 }

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

Definition at line 11180 of file app_voicemail_imapstorage.c.

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

11181 {
11182    while (poll_thread_run) {
11183       struct timespec ts = { 0, };
11184       struct timeval wait;
11185 
11186       wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));
11187       ts.tv_sec = wait.tv_sec;
11188       ts.tv_nsec = wait.tv_usec * 1000;
11189 
11190       ast_mutex_lock(&poll_lock);
11191       ast_cond_timedwait(&poll_cond, &poll_lock, &ts);
11192       ast_mutex_unlock(&poll_lock);
11193 
11194       if (!poll_thread_run)
11195          break;
11196 
11197       poll_subscribed_mailboxes();
11198    }
11199 
11200    return NULL;
11201 }

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

Definition at line 1641 of file app_voicemail_imapstorage.c.

References ARRAY_LEN.

01642 {
01643 #ifdef IMAP_STORAGE
01644    if (vmu && id == 0) {
01645       return vmu->imapfolder;
01646    }
01647 #endif
01648    return (id >= 0 && id < ARRAY_LEN(mailbox_folders)) ? mailbox_folders[id] : "Unknown";
01649 }

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

Definition at line 5240 of file app_voicemail_imapstorage.c.

References __has_voicemail().

05241 {
05242    return __has_voicemail(context, mailbox, folder, 0) + (folder && strcmp(folder, "INBOX") ? 0 : __has_voicemail(context, mailbox, "Urgent", 0));
05243 }

static void mwi_sub_destroy ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11203 of file app_voicemail_imapstorage.c.

References ast_free, and mwi_sub.

11204 {
11205    ast_free(mwi_sub);
11206 }

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

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

11282 {
11283    struct mwi_sub_task *mwist;
11284    
11285    if (ast_event_get_type(event) != AST_EVENT_SUB)
11286       return;
11287 
11288    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11289       return;
11290 
11291    if ((mwist = ast_calloc(1, (sizeof(*mwist)))) == NULL) {
11292       ast_log(LOG_ERROR, "could not allocate a mwi_sub_task\n");
11293       return;
11294    }
11295    mwist->mailbox = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX));
11296    mwist->context = ast_strdup(ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT));
11297    mwist->uniqueid = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11298    
11299    if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {
11300       ast_free(mwist);
11301    }
11302 }

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

Definition at line 11265 of file app_voicemail_imapstorage.c.

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

11266 {
11267    uint32_t u, *uniqueid = ast_calloc(1, sizeof(*uniqueid));
11268    if (ast_event_get_type(event) != AST_EVENT_UNSUB)
11269       return;
11270 
11271    if (ast_event_get_ie_uint(event, AST_EVENT_IE_EVENTTYPE) != AST_EVENT_MWI)
11272       return;
11273 
11274    u = ast_event_get_ie_uint(event, AST_EVENT_IE_UNIQUEID);
11275    *uniqueid = u;
11276    if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {
11277       ast_free(uniqueid);
11278    }
11279 }

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 6876 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, strsep(), VM_ATTACH, vm_delete(), and VM_DELETE.

06877 {
06878    char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
06879    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
06880    const char *category;
06881    char *myserveremail = serveremail;
06882 
06883    ast_channel_lock(chan);
06884    if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) {
06885       category = ast_strdupa(category);
06886    }
06887    ast_channel_unlock(chan);
06888 
06889 #ifndef IMAP_STORAGE
06890    make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, !ast_strlen_zero(flag) && !strcmp(flag, "Urgent") ? "Urgent" : "INBOX");
06891 #else
06892    snprintf(todir, sizeof(todir), "%simap", VM_SPOOL_DIR);
06893 #endif
06894    make_file(fn, sizeof(fn), todir, msgnum);
06895    snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
06896 
06897    if (!ast_strlen_zero(vmu->attachfmt)) {
06898       if (strstr(fmt, vmu->attachfmt))
06899          fmt = vmu->attachfmt;
06900       else
06901          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);
06902    }
06903 
06904    /* Attach only the first format */
06905    fmt = ast_strdupa(fmt);
06906    stringp = fmt;
06907    strsep(&stringp, "|");
06908 
06909    if (!ast_strlen_zero(vmu->serveremail))
06910       myserveremail = vmu->serveremail;
06911 
06912    if (!ast_strlen_zero(vmu->email)) {
06913       int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
06914 
06915       if (attach_user_voicemail)
06916          RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
06917 
06918       /* XXX possible imap issue, should category be NULL XXX */
06919       sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
06920 
06921       if (attach_user_voicemail)
06922          DISPOSE(todir, msgnum);
06923    }
06924 
06925    if (!ast_strlen_zero(vmu->pager)) {
06926       sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
06927    }
06928 
06929    if (ast_test_flag(vmu, VM_DELETE))
06930       DELETE(todir, msgnum, fn, vmu);
06931 
06932    /* Leave voicemail for someone */
06933    if (ast_app_has_voicemail(ext_context, NULL)) 
06934       ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs);
06935 
06936    queue_mwi_event(ext_context, urgentmsgs, newmsgs, oldmsgs);
06937 
06938    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);
06939    run_externnotify(vmu->context, vmu->mailbox, flag);
06940 
06941 #ifdef IMAP_STORAGE
06942    vm_delete(fn);  /* Delete the file, but not the IMAP message */
06943    if (ast_test_flag(vmu, VM_DELETE))  { /* Delete the IMAP message if delete = yes */
06944       vm_imap_delete(NULL, vms->curmsg, vmu);
06945       vms->newmessages--;  /* Fix new message count */
06946    }
06947 #endif
06948 
06949    return 0;
06950 }

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

utility used by base_encode()

Definition at line 4114 of file app_voicemail_imapstorage.c.

References BASELINELEN, ENDL, and baseio::linelength.

04115 {
04116    if (bio->linelength >= BASELINELEN) {
04117       if (fputs(ENDL, so) == EOF) {
04118          return -1;
04119       }
04120 
04121       bio->linelength = 0;
04122    }
04123 
04124    if (putc(((unsigned char) c), so) == EOF) {
04125       return -1;
04126    }
04127 
04128    bio->linelength++;
04129 
04130    return 1;
04131 }

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

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

07711 {
07712    int count_msg, last_msg;
07713 
07714    ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox));
07715 
07716    /* Rename the member vmbox HERE so that we don't try to return before
07717     * we know what's going on.
07718     */
07719    snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
07720 
07721    /* Faster to make the directory than to check if it exists. */
07722    create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
07723 
07724    /* traverses directory using readdir (or select query for ODBC) */
07725    count_msg = count_messages(vmu, vms->curdir);
07726    if (count_msg < 0) {
07727       return count_msg;
07728    } else {
07729       vms->lastmsg = count_msg - 1;
07730    }
07731 
07732    if (vm_allocate_dh(vms, vmu, count_msg)) {
07733       return -1;
07734    }
07735 
07736    /*
07737    The following test is needed in case sequencing gets messed up.
07738    There appears to be more than one way to mess up sequence, so
07739    we will not try to find all of the root causes--just fix it when
07740    detected.
07741    */
07742 
07743    if (vm_lock_path(vms->curdir)) {
07744       ast_log(AST_LOG_ERROR, "Could not open mailbox %s:  mailbox is locked\n", vms->curdir);
07745       return ERROR_LOCK_PATH;
07746    }
07747 
07748    /* for local storage, checks directory for messages up to maxmsg limit */
07749    last_msg = last_message_index(vmu, vms->curdir);
07750    ast_unlock_path(vms->curdir);
07751 
07752    if (last_msg < -1) {
07753       return last_msg;
07754 #ifndef ODBC_STORAGE
07755    } else if (vms->lastmsg != last_msg) {
07756       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);
07757         resequence_mailbox(vmu, vms->curdir, count_msg);
07758 #endif
07759    }
07760 
07761    return 0;
07762 }

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

Definition at line 7496 of file app_voicemail_imapstorage.c.

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

07497 {
07498    int res = 0;
07499    char filename[256], *cid;
07500    const char *origtime, *context, *category, *duration, *flag;
07501    struct ast_config *msg_cfg;
07502    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
07503 
07504    vms->starting = 0;
07505    make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07506    adsi_message(chan, vms);
07507    if (!vms->curmsg)
07508       res = wait_file2(chan, vms, "vm-first");  /* "First" */
07509    else if (vms->curmsg == vms->lastmsg)
07510       res = wait_file2(chan, vms, "vm-last");      /* "last" */
07511 
07512    snprintf(filename, sizeof(filename), "%s.txt", vms->fn);
07513    RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
07514    msg_cfg = ast_config_load(filename, config_flags);
07515    if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) {
07516       ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07517       return 0;
07518    }
07519    flag = ast_variable_retrieve(msg_cfg, "message", "flag");
07520 
07521    /* Play the word urgent if we are listening to urgent messages */
07522    if (!ast_strlen_zero(flag) && !strcmp(flag, "Urgent")) {
07523       res = wait_file2(chan, vms, "vm-Urgent"); /* "urgent" */
07524    }
07525 
07526    if (!res) {
07527       /* XXX Why are we playing messages above, and then playing the same language-specific stuff here? */
07528       /* POLISH syntax */
07529       if (!strncasecmp(chan->language, "pl", 2)) {
07530          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07531             int ten, one;
07532             char nextmsg[256];
07533             ten = (vms->curmsg + 1) / 10;
07534             one = (vms->curmsg + 1) % 10;
07535 
07536             if (vms->curmsg < 20) {
07537                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
07538                res = wait_file2(chan, vms, nextmsg);
07539             } else {
07540                snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
07541                res = wait_file2(chan, vms, nextmsg);
07542                if (one > 0) {
07543                   if (!res) {
07544                      snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
07545                      res = wait_file2(chan, vms, nextmsg);
07546                   }
07547                }
07548             }
07549          }
07550          if (!res)
07551             res = wait_file2(chan, vms, "vm-message");
07552       /* HEBREW syntax */
07553       } else if (!strncasecmp(chan->language, "he", 2)) {
07554          if (!vms->curmsg) {
07555             res = wait_file2(chan, vms, "vm-message");
07556             res = wait_file2(chan, vms, "vm-first");
07557          } else if (vms->curmsg == vms->lastmsg) {
07558             res = wait_file2(chan, vms, "vm-message");
07559             res = wait_file2(chan, vms, "vm-last");
07560          } else {
07561             res = wait_file2(chan, vms, "vm-message");
07562             res = wait_file2(chan, vms, "vm-number");
07563             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07564          }
07565       /* VIETNAMESE syntax */
07566       } else if (!strncasecmp(chan->language, "vi", 2)) {
07567          if (!vms->curmsg) {
07568             res = wait_file2(chan, vms, "vm-message");
07569             res = wait_file2(chan, vms, "vm-first");
07570          } else if (vms->curmsg == vms->lastmsg) {
07571             res = wait_file2(chan, vms, "vm-message");
07572             res = wait_file2(chan, vms, "vm-last");
07573          } else {
07574             res = wait_file2(chan, vms, "vm-message");
07575             res = wait_file2(chan, vms, "vm-number");
07576             res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, "f");
07577          }
07578       } else {
07579          if (!strncasecmp(chan->language, "se", 2)) { /* SWEDISH syntax */
07580             res = wait_file2(chan, vms, "vm-meddelandet");  /* "message" */
07581          } else { /* DEFAULT syntax */
07582             res = wait_file2(chan, vms, "vm-message");
07583          }
07584          if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
07585             if (!res) {
07586                res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
07587             }
07588          }
07589       }
07590    }
07591 
07592    if (!msg_cfg) {
07593       ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07594       return 0;
07595    }
07596 
07597    if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07598       ast_log(AST_LOG_WARNING, "No origtime?!\n");
07599       DISPOSE(vms->curdir, vms->curmsg);
07600       ast_config_destroy(msg_cfg);
07601       return 0;
07602    }
07603 
07604    cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07605    duration = ast_variable_retrieve(msg_cfg, "message", "duration");
07606    category = ast_variable_retrieve(msg_cfg, "message", "category");
07607 
07608    context = ast_variable_retrieve(msg_cfg, "message", "context");
07609    if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */
07610       context = ast_variable_retrieve(msg_cfg, "message", "macrocontext");
07611    if (!res) {
07612       res = play_message_category(chan, category);
07613    }
07614    if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
07615       res = play_message_datetime(chan, vmu, origtime, filename);
07616    if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
07617       res = play_message_callerid(chan, vms, cid, context, 0);
07618    if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
07619       res = play_message_duration(chan, vms, duration, vmu->saydurationm);
07620    /* Allow pressing '1' to skip envelope / callerid */
07621    if (res == '1')
07622       res = 0;
07623    ast_config_destroy(msg_cfg);
07624 
07625    if (!res) {
07626       make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
07627       vms->heard[vms->curmsg] = 1;
07628 #ifdef IMAP_STORAGE
07629       /*IMAP storage stores any prepended message from a forward
07630        * as a separate file from the rest of the message
07631        */
07632       if (!ast_strlen_zero(vms->introfn) && ast_fileexists(vms->introfn, NULL, NULL) > 0) {
07633          wait_file(chan, vms, vms->introfn);
07634       }
07635 #endif
07636       if ((res = wait_file(chan, vms, vms->fn)) < 0) {
07637          ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn);
07638          res = 0;
07639       }
07640    }
07641    DISPOSE(vms->curdir, vms->curmsg);
07642    return res;
07643 }

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

Definition at line 7382 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, and wait_file2().

07383 {
07384    int res = 0;
07385    int i;
07386    char *callerid, *name;
07387    char prefile[PATH_MAX] = "";
07388    
07389 
07390    /* If voicemail cid is not enabled, or we didn't get cid or context from
07391     * the attribute file, leave now.
07392     *
07393     * TODO Still need to change this so that if this function is called by the
07394     * message envelope (and someone is explicitly requesting to hear the CID),
07395     * it does not check to see if CID is enabled in the config file.
07396     */
07397    if ((cid == NULL)||(context == NULL))
07398       return res;
07399 
07400    /* Strip off caller ID number from name */
07401    ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
07402    ast_callerid_parse(cid, &name, &callerid);
07403    if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
07404       /* Check for internal contexts and only */
07405       /* say extension when the call didn't come from an internal context in the list */
07406       for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
07407          ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
07408          if ((strcmp(cidinternalcontexts[i], context) == 0))
07409             break;
07410       }
07411       if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
07412          if (!res) {
07413             snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
07414             if (!ast_strlen_zero(prefile)) {
07415             /* See if we can find a recorded name for this person instead of their extension number */
07416                if (ast_fileexists(prefile, NULL, NULL) > 0) {
07417                   ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
07418                   if (!callback)
07419                      res = wait_file2(chan, vms, "vm-from");
07420                   res = ast_stream_and_wait(chan, prefile, "");
07421                } else {
07422                   ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
07423                   /* Say "from extension" as one saying to sound smoother */
07424                   if (!callback)
07425                      res = wait_file2(chan, vms, "vm-from-extension");
07426                   res = ast_say_digit_str(chan, callerid, "", chan->language);
07427                }
07428             }
07429          }
07430       } else if (!res) {
07431          ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
07432          /* Since this is all nicely figured out, why not say "from phone number" in this case? */
07433          if (!callback)
07434             res = wait_file2(chan, vms, "vm-from-phonenumber");
07435          res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
07436       }
07437    } else {
07438       /* Number unknown */
07439       ast_debug(1, "VM-CID: From an unknown number\n");
07440       /* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
07441       res = wait_file2(chan, vms, "vm-unknown-caller");
07442    }
07443    return res;
07444 }

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

Definition at line 7293 of file app_voicemail_imapstorage.c.

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

07294 {
07295    int res = 0;
07296 
07297    if (!ast_strlen_zero(category))
07298       res = ast_play_and_wait(chan, category);
07299 
07300    if (res) {
07301       ast_log(AST_LOG_WARNING, "No sound file for category '%s' was found.\n", category);
07302       res = 0;
07303    }
07304 
07305    return res;
07306 }

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

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

07309 {
07310    int res = 0;
07311    struct vm_zone *the_zone = NULL;
07312    time_t t;
07313 
07314    if (ast_get_time_t(origtime, &t, 0, NULL)) {
07315       ast_log(AST_LOG_WARNING, "Couldn't find origtime in %s\n", filename);
07316       return 0;
07317    }
07318 
07319    /* Does this user have a timezone specified? */
07320    if (!ast_strlen_zero(vmu->zonetag)) {
07321       /* Find the zone in the list */
07322       struct vm_zone *z;
07323       AST_LIST_LOCK(&zones);
07324       AST_LIST_TRAVERSE(&zones, z, list) {
07325          if (!strcmp(z->name, vmu->zonetag)) {
07326             the_zone = z;
07327             break;
07328          }
07329       }
07330       AST_LIST_UNLOCK(&zones);
07331    }
07332 
07333 /* No internal variable parsing for now, so we'll comment it out for the time being */
07334 #if 0
07335    /* Set the DIFF_* variables */
07336    ast_localtime(&t, &time_now, NULL);
07337    tv_now = ast_tvnow();
07338    ast_localtime(&tv_now, &time_then, NULL);
07339 
07340    /* Day difference */
07341    if (time_now.tm_year == time_then.tm_year)
07342       snprintf(temp, sizeof(temp), "%d", time_now.tm_yday);
07343    else
07344       snprintf(temp, sizeof(temp), "%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
07345    pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
07346 
07347    /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
07348 #endif
07349    if (the_zone) {
07350       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
07351    } else if (!strncasecmp(chan->language, "de", 2)) {     /* GERMAN syntax */
07352       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07353    } else if (!strncasecmp(chan->language, "gr", 2)) {     /* GREEK syntax */
07354       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q  H 'digits/kai' M ", NULL);
07355    } else if (!strncasecmp(chan->language, "it", 2)) {     /* ITALIAN syntax */
07356       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);
07357    } else if (!strncasecmp(chan->language, "nl", 2)) {     /* DUTCH syntax */
07358       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
07359    } else if (!strncasecmp(chan->language, "no", 2)) {     /* NORWEGIAN syntax */
07360       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
07361    } else if (!strncasecmp(chan->language, "pl", 2)) {     /* POLISH syntax */
07362       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
07363    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* Brazillian PORTUGUESE syntax */
07364       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);
07365    } else if (!strncasecmp(chan->language, "se", 2)) {     /* SWEDISH syntax */
07366       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
07367    } else if (!strncasecmp(chan->language, "zh", 2)) {     /* CHINESE (Taiwan) syntax */
07368       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
07369    } else if (!strncasecmp(chan->language, "vi", 2)) {     /* VIETNAMESE syntax */
07370       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);
07371    } else {
07372       res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
07373    }
07374 #if 0
07375    pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
07376 #endif
07377    return res;
07378 }

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

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

07447 {
07448    int res = 0;
07449    int durationm;
07450    int durations;
07451    /* Verify that we have a duration for the message */
07452    if (duration == NULL)
07453       return res;
07454 
07455    /* Convert from seconds to minutes */
07456    durations = atoi(duration);
07457    durationm = (durations / 60);
07458 
07459    ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
07460 
07461    if ((!res) && (durationm >= minduration)) {
07462       res = wait_file2(chan, vms, "vm-duration");
07463 
07464       /* POLISH syntax */
07465       if (!strncasecmp(chan->language, "pl", 2)) {
07466          div_t num = div(durationm, 10);
07467 
07468          if (durationm == 1) {
07469             res = ast_play_and_wait(chan, "digits/1z");
07470             res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
07471          } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
07472             if (num.rem == 2) {
07473                if (!num.quot) {
07474                   res = ast_play_and_wait(chan, "digits/2-ie");
07475                } else {
07476                   res = say_and_wait(chan, durationm - 2 , chan->language);
07477                   res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
07478                }
07479             } else {
07480                res = say_and_wait(chan, durationm, chan->language);
07481             }
07482             res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
07483          } else {
07484             res = say_and_wait(chan, durationm, chan->language);
07485             res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
07486          }
07487       /* DEFAULT syntax */
07488       } else {
07489          res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
07490          res = wait_file2(chan, vms, "vm-minutes");
07491       }
07492    }
07493    return res;
07494 }

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,
const char *  unlockdir,
signed char  record_gain,
struct vm_state vms,
char *  flag 
) [static]

Definition at line 12997 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, STORE, VERBOSE_PREFIX_3, vm_exec(), VM_OPERATOR, and VM_REVIEW.

13000 {
13001    /* Record message & let caller review or re-record it, or set options if applicable */
13002    int res = 0;
13003    int cmd = 0;
13004    int max_attempts = 3;
13005    int attempts = 0;
13006    int recorded = 0;
13007    int msg_exists = 0;
13008    signed char zero_gain = 0;
13009    char tempfile[PATH_MAX];
13010    char *acceptdtmf = "#";
13011    char *canceldtmf = "";
13012    int canceleddtmf = 0;
13013 
13014    /* Note that urgent and private are for flagging messages as such in the future */
13015 
13016    /* barf if no pointer passed to store duration in */
13017    if (duration == NULL) {
13018       ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n");
13019       return -1;
13020    }
13021 
13022    if (!outsidecaller)
13023       snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
13024    else
13025       ast_copy_string(tempfile, recordfile, sizeof(tempfile));
13026 
13027    cmd = '3';  /* Want to start by recording */
13028 
13029    while ((cmd >= 0) && (cmd != 't')) {
13030       switch (cmd) {
13031       case '1':
13032          if (!msg_exists) {
13033             /* In this case, 1 is to record a message */
13034             cmd = '3';
13035             break;
13036          } else {
13037             /* Otherwise 1 is to save the existing message */
13038             ast_verb(3, "Saving message as is\n");
13039             if (!outsidecaller) 
13040                ast_filerename(tempfile, recordfile, NULL);
13041             ast_stream_and_wait(chan, "vm-msgsaved", "");
13042             if (!outsidecaller) {
13043                /* Saves to IMAP server only if imapgreeting=yes */
13044                STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag);
13045                DISPOSE(recordfile, -1);
13046             }
13047             cmd = 't';
13048             return res;
13049          }
13050       case '2':
13051          /* Review */
13052          ast_verb(3, "Reviewing the message\n");
13053          cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY);
13054          break;
13055       case '3':
13056          msg_exists = 0;
13057          /* Record */
13058          if (recorded == 1) 
13059             ast_verb(3, "Re-recording the message\n");
13060          else  
13061             ast_verb(3, "Recording the message\n");
13062          
13063          if (recorded && outsidecaller) {
13064             cmd = ast_play_and_wait(chan, INTRO);
13065             cmd = ast_play_and_wait(chan, "beep");
13066          }
13067          recorded = 1;
13068          /* 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 */
13069          if (record_gain)
13070             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
13071          if (ast_test_flag(vmu, VM_OPERATOR))
13072             canceldtmf = "0";
13073          cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13074          if (strchr(canceldtmf, cmd)) {
13075          /* need this flag here to distinguish between pressing '0' during message recording or after */
13076             canceleddtmf = 1;
13077          }
13078          if (record_gain)
13079             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
13080          if (cmd == -1) {
13081             /* User has hung up, no options to give */
13082             if (!outsidecaller) {
13083                /* user was recording a greeting and they hung up, so let's delete the recording. */
13084                ast_filedelete(tempfile, NULL);
13085             }     
13086             return cmd;
13087          }
13088          if (cmd == '0') {
13089             break;
13090          } else if (cmd == '*') {
13091             break;
13092 #if 0
13093          } else if (vmu->review && (*duration < 5)) {
13094             /* Message is too short */
13095             ast_verb(3, "Message too short\n");
13096             cmd = ast_play_and_wait(chan, "vm-tooshort");
13097             cmd = ast_filedelete(tempfile, NULL);
13098             break;
13099          } else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
13100             /* Message is all silence */
13101             ast_verb(3, "Nothing recorded\n");
13102             cmd = ast_filedelete(tempfile, NULL);
13103             cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
13104             if (!cmd)
13105                cmd = ast_play_and_wait(chan, "vm-speakup");
13106             break;
13107 #endif
13108          } else {
13109             /* If all is well, a message exists */
13110             msg_exists = 1;
13111             cmd = 0;
13112          }
13113          break;
13114       case '4':
13115          if (outsidecaller) {  /* only mark vm messages */
13116             /* Mark Urgent */
13117             if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13118                ast_verbose(VERBOSE_PREFIX_3 "marking message as Urgent\n");
13119                res = ast_play_and_wait(chan, "vm-marked-urgent");
13120                strcpy(flag, "Urgent");
13121             } else if (flag) {
13122                ast_verbose(VERBOSE_PREFIX_3 "UNmarking message as Urgent\n");
13123                res = ast_play_and_wait(chan, "vm-urgent-removed");
13124                strcpy(flag, "");
13125             } else {
13126                ast_play_and_wait(chan, "vm-sorry");
13127             }
13128             cmd = 0;
13129          } else {
13130             cmd = ast_play_and_wait(chan, "vm-sorry");
13131          }
13132          break;
13133       case '5':
13134       case '6':
13135       case '7':
13136       case '8':
13137       case '9':
13138       case '*':
13139       case '#':
13140          cmd = ast_play_and_wait(chan, "vm-sorry");
13141          break;
13142 #if 0 
13143 /*  XXX Commented out for the moment because of the dangers of deleting
13144     a message while recording (can put the message numbers out of sync) */
13145       case '*':
13146          /* Cancel recording, delete message, offer to take another message*/
13147          cmd = ast_play_and_wait(chan, "vm-deleted");
13148          cmd = ast_filedelete(tempfile, NULL);
13149          if (outsidecaller) {
13150             res = vm_exec(chan, NULL);
13151             return res;
13152          }
13153          else
13154             return 1;
13155 #endif
13156       case '0':
13157          if (!ast_test_flag(vmu, VM_OPERATOR) || (!canceleddtmf && !outsidecaller)) {
13158             cmd = ast_play_and_wait(chan, "vm-sorry");
13159             break;
13160          }
13161          if (msg_exists || recorded) {
13162             cmd = ast_play_and_wait(chan, "vm-saveoper");
13163             if (!cmd)
13164                cmd = ast_waitfordigit(chan, 3000);
13165             if (cmd == '1') {
13166                ast_filerename(tempfile, recordfile, NULL);
13167                ast_play_and_wait(chan, "vm-msgsaved");
13168                cmd = '0';
13169             } else if (cmd == '4') {
13170                if (flag) {
13171                   ast_play_and_wait(chan, "vm-marked-urgent");
13172                   strcpy(flag, "Urgent");
13173                }
13174                ast_play_and_wait(chan, "vm-msgsaved");
13175                cmd = '0';
13176             } else {
13177                ast_play_and_wait(chan, "vm-deleted");
13178                DELETE(tempfile, -1, tempfile, vmu);
13179                cmd = '0';
13180             }
13181          }
13182          return cmd;
13183       default:
13184          /* If the caller is an ouside caller, and the review option is enabled,
13185             allow them to review the message, but let the owner of the box review
13186             their OGM's */
13187          if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
13188             return cmd;
13189          if (msg_exists) {
13190             cmd = ast_play_and_wait(chan, "vm-review");
13191             if (!cmd && outsidecaller) {
13192                if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) {
13193                   cmd = ast_play_and_wait(chan, "vm-review-urgent");
13194                } else if (flag) {
13195                   cmd = ast_play_and_wait(chan, "vm-review-nonurgent");
13196                }
13197             }
13198          } else {
13199             cmd = ast_play_and_wait(chan, "vm-torerecord");
13200             if (!cmd)
13201                cmd = ast_waitfordigit(chan, 600);
13202          }
13203          
13204          if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
13205             cmd = ast_play_and_wait(chan, "vm-reachoper");
13206             if (!cmd)
13207                cmd = ast_waitfordigit(chan, 600);
13208          }
13209 #if 0
13210          if (!cmd)
13211             cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
13212 #endif
13213          if (!cmd)
13214             cmd = ast_waitfordigit(chan, 6000);
13215          if (!cmd) {
13216             attempts++;
13217          }
13218          if (attempts > max_attempts) {
13219             cmd = 't';
13220          }
13221       }
13222    }
13223    if (!outsidecaller && (cmd == -1 || cmd == 't')) {
13224       /* Hang up or timeout, so delete the recording. */
13225       ast_filedelete(tempfile, NULL);
13226    }
13227 
13228    if (cmd != 't' && outsidecaller)
13229       ast_play_and_wait(chan, "vm-goodbye");
13230 
13231    return cmd;
13232 }

static void poll_subscribed_mailbox ( struct mwi_sub mwi_sub  )  [static]

Definition at line 11152 of file app_voicemail_imapstorage.c.

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

11153 {
11154    int new = 0, old = 0, urgent = 0;
11155 
11156    inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);
11157 
11158    if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {
11159       mwi_sub->old_urgent = urgent;
11160       mwi_sub->old_new = new;
11161       mwi_sub->old_old = old;
11162       queue_mwi_event(mwi_sub->mailbox, urgent, new, old);
11163       run_externnotify(NULL, mwi_sub->mailbox, NULL);
11164    }
11165 }

static void poll_subscribed_mailboxes ( void   )  [static]

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

11168 {
11169    struct mwi_sub *mwi_sub;
11170 
11171    AST_RWLIST_RDLOCK(&mwi_subs);
11172    AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {
11173       if (!ast_strlen_zero(mwi_sub->mailbox)) {
11174          poll_subscribed_mailbox(mwi_sub);
11175       }
11176    }
11177    AST_RWLIST_UNLOCK(&mwi_subs);
11178 }

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

References ast_copy_flags, ast_copy_string(), AST_FLAGS_ALL, 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.

00970 {
00971    ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);   
00972    vmu->passwordlocation = passwordlocation;
00973    if (saydurationminfo) {
00974       vmu->saydurationm = saydurationminfo;
00975    }
00976    ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00977    ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00978    ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00979    ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
00980    ast_copy_string(vmu->locale, locale, sizeof(vmu->locale));
00981    if (vmminsecs) {
00982       vmu->minsecs = vmminsecs;
00983    }
00984    if (vmmaxsecs) {
00985       vmu->maxsecs = vmmaxsecs;
00986    }
00987    if (maxmsg) {
00988       vmu->maxmsg = maxmsg;
00989    }
00990    if (maxdeletedmsg) {
00991       vmu->maxdeletedmsg = maxdeletedmsg;
00992    }
00993    vmu->volgain = volgain;
00994    vmu->emailsubject = NULL;
00995    vmu->emailbody = NULL;
00996 #ifdef IMAP_STORAGE
00997    ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
00998 #endif
00999 }

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

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

04203 {
04204    char callerid[256];
04205    char num[12];
04206    char fromdir[256], fromfile[256];
04207    struct ast_config *msg_cfg;
04208    const char *origcallerid, *origtime;
04209    char origcidname[80], origcidnum[80], origdate[80];
04210    int inttime;
04211    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
04212 
04213    /* Prepare variables for substitution in email body and subject */
04214    pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
04215    pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
04216    snprintf(num, sizeof(num), "%d", msgnum);
04217    pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
04218    pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
04219    pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
04220    pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
04221       ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller");
04222    pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller"));
04223    pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (!ast_strlen_zero(cidnum) ? cidnum : "an unknown caller"));
04224    pbx_builtin_setvar_helper(ast, "VM_DATE", date);
04225    pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
04226    pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
04227 
04228    /* Retrieve info from VM attribute file */
04229    make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
04230    make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
04231    if (strlen(fromfile) < sizeof(fromfile) - 5) {
04232       strcat(fromfile, ".txt");
04233    }
04234    if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
04235       if (option_debug > 0) {
04236          ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
04237       }
04238       return;
04239    }
04240 
04241    if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
04242       pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
04243       ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
04244       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
04245       pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
04246    }
04247 
04248    if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) {
04249       struct timeval tv = { inttime, };
04250       struct ast_tm tm;
04251       ast_localtime(&tv, &tm, NULL);
04252       ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL));
04253       pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
04254    }
04255    ast_config_destroy(msg_cfg);
04256 }

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

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

06840 {
06841    struct ast_event *event;
06842    char *mailbox, *context;
06843 
06844    /* Strip off @default */
06845    context = mailbox = ast_strdupa(box);
06846    strsep(&context, "@");
06847    if (ast_strlen_zero(context))
06848       context = "default";
06849 
06850    if (!(event = ast_event_new(AST_EVENT_MWI,
06851          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
06852          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
06853          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
06854          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
06855          AST_EVENT_IE_END))) {
06856       return;
06857    }
06858 
06859    ast_event_queue_and_cache(event);
06860 }

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

Definition at line 12214 of file app_voicemail_imapstorage.c.

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

12214                                                                                            {
12215    struct ast_config *pwconf;
12216    struct ast_flags config_flags = { 0 };
12217 
12218    pwconf = ast_config_load(secretfn, config_flags);
12219    if (pwconf) {
12220       const char *val = ast_variable_retrieve(pwconf, "general", "password");
12221       if (val) {
12222          ast_copy_string(password, val, passwordlen);
12223          return;
12224       }
12225    }
12226    ast_log(LOG_NOTICE, "Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12227 }

static int reload ( void   )  [static]

Definition at line 12651 of file app_voicemail_imapstorage.c.

References load_config().

12652 {
12653    return load_config(1);
12654 }

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

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

03872 {
03873    char stxt[PATH_MAX];
03874    char dtxt[PATH_MAX];
03875    ast_filerename(sfn, dfn, NULL);
03876    snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
03877    snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
03878    if (ast_check_realtime("voicemail_data")) {
03879       ast_update_realtime("voicemail_data", "filename", sfn, "filename", dfn, SENTINEL);
03880    }
03881    rename(stxt, dtxt);
03882 }

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

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

06010 {
06011     /* we know the actual number of messages, so stop process when number is hit */
06012 
06013     int x, dest;
06014     char sfn[PATH_MAX];
06015     char dfn[PATH_MAX];
06016 
06017     if (vm_lock_path(dir))
06018         return ERROR_LOCK_PATH;
06019 
06020     for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) {
06021         make_file(sfn, sizeof(sfn), dir, x);
06022         if (EXISTS(dir, x, sfn, NULL)) {
06023 
06024             if (x != dest) {
06025                 make_file(dfn, sizeof(dfn), dir, dest);
06026                 RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
06027             }
06028 
06029             dest++;
06030         }
06031     }
06032     ast_unlock_path(dir);
06033 
06034     return dest;
06035 }

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

01414 {
01415    /* This function could be made to generate one from a database, too */
01416    struct ast_vm_user *cur;
01417    int res = -1;
01418    AST_LIST_LOCK(&users);
01419    AST_LIST_TRAVERSE(&users, cur, list) {
01420       if ((!context || !strcasecmp(context, cur->context)) &&
01421          (!strcasecmp(mailbox, cur->mailbox)))
01422             break;
01423    }
01424    if (cur) {
01425       ast_copy_string(cur->password, newpass, sizeof(cur->password));
01426       res = 0;
01427    }
01428    AST_LIST_UNLOCK(&users);
01429    return res;
01430 }

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

Definition at line 5383 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, ast_smdi_mwi_message::fwd_st, inboxcount2(), smdi_iface, and SMDI_MWI_WAIT_TIMEOUT.

05384 {
05385    char arguments[255];
05386    char ext_context[256] = "";
05387    int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
05388    struct ast_smdi_mwi_message *mwi_msg;
05389 
05390    if (!ast_strlen_zero(context))
05391       snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
05392    else
05393       ast_copy_string(ext_context, extension, sizeof(ext_context));
05394 
05395    if (smdi_iface) {
05396       if (ast_app_has_voicemail(ext_context, NULL)) 
05397          ast_smdi_mwi_set(smdi_iface, extension);
05398       else
05399          ast_smdi_mwi_unset(smdi_iface, extension);
05400 
05401       if ((mwi_msg = ast_smdi_mwi_message_wait_station(smdi_iface, SMDI_MWI_WAIT_TIMEOUT, extension))) {
05402          ast_log(AST_LOG_ERROR, "Error executing SMDI MWI change for %s\n", extension);
05403          if (!strncmp(mwi_msg->cause, "INV", 3))
05404             ast_log(AST_LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
05405          else if (!strncmp(mwi_msg->cause, "BLK", 3))
05406             ast_log(AST_LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
05407          ast_log(AST_LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
05408          ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
05409       } else {
05410          ast_debug(1, "Successfully executed SMDI MWI change for %s\n", extension);
05411       }
05412    }
05413 
05414    if (!ast_strlen_zero(externnotify)) {
05415       if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
05416          ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
05417       } else {
05418          snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
05419          ast_debug(1, "Executing %s\n", arguments);
05420          ast_safe_system(arguments);
05421       }
05422    }
05423 }

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

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

06046 {
06047 #ifdef IMAP_STORAGE
06048    /* we must use mbox(x) folder names, and copy the message there */
06049    /* simple. huh? */
06050    char sequence[10];
06051    char mailbox[256];
06052    int res;
06053 
06054    /* get the real IMAP message number for this message */
06055    snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]);
06056    
06057    ast_debug(3, "Copying sequence %s to mailbox %s\n", sequence, mbox(vmu, box));
06058    ast_mutex_lock(&vms->lock);
06059    /* if save to Old folder, put in INBOX as read */
06060    if (box == OLD_FOLDER) {
06061       mail_setflag(vms->mailstream, sequence, "\\Seen");
06062       mail_clearflag(vms->mailstream, sequence, "\\Unseen");
06063    } else if (box == NEW_FOLDER) {
06064       mail_setflag(vms->mailstream, sequence, "\\Unseen");
06065       mail_clearflag(vms->mailstream, sequence, "\\Seen");
06066    }
06067    if (!strcasecmp(mbox(vmu, NEW_FOLDER), vms->curbox) && (box == NEW_FOLDER || box == OLD_FOLDER)) {
06068       ast_mutex_unlock(&vms->lock);
06069       return 0;
06070    }
06071    /* Create the folder if it don't exist */
06072    imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
06073    ast_debug(5, "Checking if folder exists: %s\n", mailbox);
06074    if (mail_create(vms->mailstream, mailbox) == NIL) 
06075       ast_debug(5, "Folder exists.\n");
06076    else
06077       ast_log(AST_LOG_NOTICE, "Folder %s created!\n", mbox(vmu, box));
06078    res = !mail_copy(vms->mailstream, sequence, (char *) mbox(vmu, box));
06079    ast_mutex_unlock(&vms->lock);
06080    return res;
06081 #else
06082    char *dir = vms->curdir;
06083    char *username = vms->username;
06084    char *context = vmu->context;
06085    char sfn[PATH_MAX];
06086    char dfn[PATH_MAX];
06087    char ddir[PATH_MAX];
06088    const char *dbox = mbox(vmu, box);
06089    int x, i;
06090    create_dirpath(ddir, sizeof(ddir), context, username, dbox);
06091 
06092    if (vm_lock_path(ddir))
06093       return ERROR_LOCK_PATH;
06094 
06095    x = last_message_index(vmu, ddir) + 1;
06096 
06097    if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/
06098       x--;
06099       for (i = 1; i <= x; i++) {
06100          /* Push files down a "slot".  The oldest file (msg0000) will be deleted. */
06101          make_file(sfn, sizeof(sfn), ddir, i);
06102          make_file(dfn, sizeof(dfn), ddir, i - 1);
06103          if (EXISTS(ddir, i, sfn, NULL)) {
06104             RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn);
06105          } else
06106             break;
06107       }
06108    } else {
06109       if (x >= vmu->maxmsg) {
06110          ast_unlock_path(ddir);
06111          return -1;
06112       }
06113    }
06114    make_file(sfn, sizeof(sfn), dir, msg);
06115    make_file(dfn, sizeof(dfn), ddir, x);
06116    if (strcmp(sfn, dfn)) {
06117       COPY(dir, msg, ddir, x, username, context, sfn, dfn);
06118    }
06119    ast_unlock_path(ddir);
06120 #endif
06121    return 0;
06122 }

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

Definition at line 6038 of file app_voicemail_imapstorage.c.

References AST_DIGIT_ANY, and ast_say_number().

06039 {
06040    int d;
06041    d = ast_say_number(chan, num, AST_DIGIT_ANY, language, NULL);
06042    return d;
06043 }

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

Definition at line 12200 of file app_voicemail_imapstorage.c.

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

12201 {
12202    int res = -1;
12203    char dir[PATH_MAX];
12204    snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12205    ast_debug(2, "About to try retrieving name file %s\n", dir);
12206    RETRIEVE(dir, -1, mailbox, context);
12207    if (ast_fileexists(dir, NULL, NULL)) {
12208       res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY);
12209    }
12210    DISPOSE(dir, -1);
12211    return res;
12212 }

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 4715 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, make_email_file(), strsep(), VM_ATTACH, and vm_mkftemp().

04716 {
04717    FILE *p = NULL;
04718    char tmp[80] = "/tmp/astmail-XXXXXX";
04719    char tmp2[256];
04720    char *stringp;
04721 
04722    if (vmu && ast_strlen_zero(vmu->email)) {
04723       ast_log(AST_LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->mailbox);
04724       return(0);
04725    }
04726 
04727    /* Mail only the first format */
04728    format = ast_strdupa(format);
04729    stringp = format;
04730    strsep(&stringp, "|");
04731 
04732    if (!strcmp(format, "wav49"))
04733       format = "WAV";
04734    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));
04735    /* Make a temporary file instead of piping directly to sendmail, in case the mail
04736       command hangs */
04737    if ((p = vm_mkftemp(tmp)) == NULL) {
04738       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04739       return -1;
04740    } else {
04741       make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
04742       fclose(p);
04743       snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04744       ast_safe_system(tmp2);
04745       ast_debug(1, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
04746    }
04747    return 0;
04748 }

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

References ast_channel_release(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc(), ast_free, ast_log(), ast_safe_system(), ast_str_buffer(), ast_str_create(), ast_str_encode_mime(), ast_str_quote(), ast_str_set(), ast_str_substitute_variables(), ast_strftime_locale(), ast_strlen_zero(), check_mime(), ENDL, ast_vm_user::fullname, ast_vm_user::locale, MAXHOSTNAMELEN, pagerbody, pagerdateformat, pagerfromstring, pagersubject, prep_email_sub_vars(), S_OR, strip_control_and_high(), vm_mkftemp(), and vmu_tm().

04751 {
04752    char enc_cidnum[256], enc_cidname[256];
04753    char date[256];
04754    char host[MAXHOSTNAMELEN] = "";
04755    char who[256];
04756    char dur[PATH_MAX];
04757    char tmp[80] = "/tmp/astmail-XXXXXX";
04758    char tmp2[PATH_MAX];
04759    struct ast_tm tm;
04760    FILE *p;
04761    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
04762 
04763    if (!str1 || !str2) {
04764       ast_free(str1);
04765       ast_free(str2);
04766       return -1;
04767    }
04768 
04769    if (cidnum) {
04770       strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum));
04771    }
04772    if (cidname) {
04773       strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
04774    }
04775 
04776    if ((p = vm_mkftemp(tmp)) == NULL) {
04777       ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
04778       ast_free(str1);
04779       ast_free(str2);
04780       return -1;
04781    }
04782    gethostname(host, sizeof(host)-1);
04783    if (strchr(srcemail, '@')) {
04784       ast_copy_string(who, srcemail, sizeof(who));
04785    } else {
04786       snprintf(who, sizeof(who), "%s@%s", srcemail, host);
04787    }
04788    snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
04789    ast_strftime_locale(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04790    fprintf(p, "Date: %s\n", date);
04791 
04792    /* Reformat for custom pager format */
04793    ast_strftime_locale(date, sizeof(date), pagerdateformat, vmu_tm(vmu, &tm), S_OR(vmu->locale, NULL));
04794 
04795    if (!ast_strlen_zero(pagerfromstring)) {
04796       struct ast_channel *ast;
04797       if ((ast = ast_dummy_channel_alloc())) {
04798          char *ptr;
04799          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
04800          ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
04801 
04802          if (check_mime(ast_str_buffer(str1))) {
04803             int first_line = 1;
04804             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
04805             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04806                *ptr = '\0';
04807                fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
04808                first_line = 0;
04809                /* Substring is smaller, so this will never grow */
04810                ast_str_set(&str2, 0, "%s", ptr + 1);
04811             }
04812             fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
04813          } else {
04814             fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
04815          }
04816          ast = ast_channel_release(ast);
04817       } else {
04818          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04819       }
04820    } else {
04821       fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
04822    }
04823 
04824    if (check_mime(vmu->fullname)) {
04825       int first_line = 1;
04826       char *ptr;
04827       ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
04828       while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04829          *ptr = '\0';
04830          fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
04831          first_line = 0;
04832          /* Substring is smaller, so this will never grow */
04833          ast_str_set(&str2, 0, "%s", ptr + 1);
04834       }
04835       fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
04836    } else {
04837       fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
04838    }
04839 
04840    if (!ast_strlen_zero(pagersubject)) {
04841       struct ast_channel *ast;
04842       if ((ast = ast_dummy_channel_alloc())) {
04843          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04844          ast_str_substitute_variables(&str1, 0, ast, pagersubject);
04845          if (check_mime(ast_str_buffer(str1))) {
04846             int first_line = 1;
04847             char *ptr;
04848             ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
04849             while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
04850                *ptr = '\0';
04851                fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04852                first_line = 0;
04853                /* Substring is smaller, so this will never grow */
04854                ast_str_set(&str2, 0, "%s", ptr + 1);
04855             }
04856             fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
04857          } else {
04858             fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
04859          }
04860          ast = ast_channel_release(ast);
04861       } else {
04862          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04863       }
04864    } else {
04865       if (ast_strlen_zero(flag)) {
04866          fprintf(p, "Subject: New VM\n\n");
04867       } else {
04868          fprintf(p, "Subject: New %s VM\n\n", flag);
04869       }
04870    }
04871 
04872    if (pagerbody) {
04873       struct ast_channel *ast;
04874       if ((ast = ast_dummy_channel_alloc())) {
04875          prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
04876          ast_str_substitute_variables(&str1, 0, ast, pagerbody);
04877          fprintf(p, "%s" ENDL, ast_str_buffer(str1));
04878          ast = ast_channel_release(ast);
04879       } else {
04880          ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
04881       }
04882    } else {
04883       fprintf(p, "New %s long %s msg in box %s\n"
04884             "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
04885    }
04886 
04887    fclose(p);
04888    snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
04889    ast_safe_system(tmp2);
04890    ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
04891    ast_free(str1);
04892    ast_free(str2);
04893    return 0;
04894 }

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

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

10810 {
10811    struct ast_config *cfg;
10812    const char *cat = NULL;
10813 
10814    if (!(cfg = ast_load_realtime_multientry("voicemail", 
10815       "context", context, SENTINEL))) {
10816       return CLI_FAILURE;
10817    }
10818 
10819    ast_cli(fd,
10820       "\n"
10821       "=============================================================\n"
10822       "=== Configured Voicemail Users ==============================\n"
10823       "=============================================================\n"
10824       "===\n");
10825 
10826    while ((cat = ast_category_browse(cfg, cat))) {
10827       struct ast_variable *var = NULL;
10828       ast_cli(fd,
10829          "=== Mailbox ...\n"
10830          "===\n");
10831       for (var = ast_variable_browse(cfg, cat); var; var = var->next)
10832          ast_cli(fd, "=== ==> %s: %s\n", var->name, var->value);
10833       ast_cli(fd,
10834          "===\n"
10835          "=== ---------------------------------------------------------\n"
10836          "===\n");
10837    }
10838 
10839    ast_cli(fd,
10840       "=============================================================\n"
10841       "\n");
10842 
10843    ast_config_destroy(cfg);
10844 
10845    return CLI_SUCCESS;
10846 }

static void start_poll_thread ( void   )  [static]

Definition at line 11304 of file app_voicemail_imapstorage.c.

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

static void stop_poll_thread ( void   )  [static]

Definition at line 11322 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, and poll_lock.

11323 {
11324    poll_thread_run = 0;
11325 
11326    if (mwi_sub_sub) {
11327       ast_event_unsubscribe(mwi_sub_sub);
11328       mwi_sub_sub = NULL;
11329    }
11330 
11331    if (mwi_unsub_sub) {
11332       ast_event_unsubscribe(mwi_unsub_sub);
11333       mwi_unsub_sub = NULL;
11334    }
11335 
11336    ast_mutex_lock(&poll_lock);
11337    ast_cond_signal(&poll_cond);
11338    ast_mutex_unlock(&poll_lock);
11339 
11340    pthread_join(poll_thread, NULL);
11341 
11342    poll_thread = AST_PTHREADT_NULL;
11343 }

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

00941 {
00942    char *bufptr = buf;
00943    for (; *input; input++) {
00944       if (*input < 32) {
00945          continue;
00946       }
00947       *bufptr++ = *input;
00948       if (bufptr == buf + buflen - 1) {
00949          break;
00950       }
00951    }
00952    *bufptr = '\0';
00953    return buf;
00954 }

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

Definition at line 11468 of file app_voicemail_imapstorage.c.

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

11469 {
11470    char *current;
11471 
11472    /* Add 16 for fudge factor */
11473    struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
11474 
11475    ast_str_reset(str);
11476    
11477    /* Substitute strings \r, \n, and \t into the appropriate characters */
11478    for (current = (char *) value; *current; current++) {
11479       if (*current == '\\') {
11480          current++;
11481          if (!*current) {
11482             ast_log(AST_LOG_NOTICE, "Incomplete escape at end of value.\n");
11483             break;
11484          }
11485          switch (*current) {
11486          case 'r':
11487             ast_str_append(&str, 0, "\r");
11488             break;
11489          case 'n':
11490 #ifdef IMAP_STORAGE
11491             if (!str->used || str->str[str->used - 1] != '\r') {
11492                ast_str_append(&str, 0, "\r");
11493             }
11494 #endif
11495             ast_str_append(&str, 0, "\n");
11496             break;
11497          case 't':
11498             ast_str_append(&str, 0, "\t");
11499             break;
11500          default:
11501             ast_log(AST_LOG_NOTICE, "Substitution routine does not support this character: \\%c\n", *current);
11502             break;
11503          }
11504       } else {
11505          ast_str_append(&str, 0, "%c", *current);
11506       }
11507    }
11508 
11509    return ast_str_buffer(str);
11510 }

static int unload_module ( void   )  [static]

Definition at line 12656 of file app_voicemail_imapstorage.c.

References ao2_ref, 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, and stop_poll_thread().

12657 {
12658    int res;
12659 
12660    res = ast_unregister_application(app);
12661    res |= ast_unregister_application(app2);
12662    res |= ast_unregister_application(app3);
12663    res |= ast_unregister_application(app4);
12664    res |= ast_unregister_application(sayname_app);
12665    res |= ast_custom_function_unregister(&mailbox_exists_acf);
12666    res |= ast_manager_unregister("VoicemailUsersList");
12667    res |= ast_data_unregister(NULL);
12668 #ifdef TEST_FRAMEWORK
12669    res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
12670    res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
12671    res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
12672    res |= AST_TEST_UNREGISTER(test_voicemail_notify_endl);
12673 #endif
12674    ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
12675    ast_uninstall_vm_functions();
12676    ao2_ref(inprocess_container, -1);
12677 
12678    if (poll_thread != AST_PTHREADT_NULL)
12679       stop_poll_thread();
12680 
12681    mwi_subscription_tps = ast_taskprocessor_unreference(mwi_subscription_tps);
12682    ast_unload_realtime("voicemail");
12683    ast_unload_realtime("voicemail_data");
12684 
12685    free_vm_users();
12686    free_vm_zones();
12687    return res;
12688 }

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

Definition at line 1679 of file app_voicemail_imapstorage.c.

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

01679                                                                                         {
01680 
01681    int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
01682    if (!vms->dh_arraysize) {
01683       /* initial allocation */
01684       if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
01685          return -1;
01686       }
01687       if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
01688          return -1;
01689       }
01690       vms->dh_arraysize = arraysize;
01691    } else if (vms->dh_arraysize < arraysize) {
01692       if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
01693          return -1;
01694       }
01695       if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
01696          return -1;
01697       }
01698       memset(vms->deleted, 0, arraysize * sizeof(int));
01699       memset(vms->heard, 0, arraysize * sizeof(int));
01700       vms->dh_arraysize = arraysize;
01701    }
01702 
01703    return 0;
01704 }

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 9541 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_verb, ast_waitstream(), find_user(), ast_vm_user::password, S_COR, and vm_password.

09544 {
09545    int useadsi = 0, valid = 0, logretries = 0;
09546    char password[AST_MAX_EXTENSION]="", *passptr;
09547    struct ast_vm_user vmus, *vmu = NULL;
09548 
09549    /* If ADSI is supported, setup login screen */
09550    adsi_begin(chan, &useadsi);
09551    if (!skipuser && useadsi)
09552       adsi_login(chan);
09553    if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
09554       ast_log(AST_LOG_WARNING, "Couldn't stream login file\n");
09555       return -1;
09556    }
09557    
09558    /* Authenticate them and get their mailbox/password */
09559    
09560    while (!valid && (logretries < max_logins)) {
09561       /* Prompt for, and read in the username */
09562       if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
09563          ast_log(AST_LOG_WARNING, "Couldn't read username\n");
09564          return -1;
09565       }
09566       if (ast_strlen_zero(mailbox)) {
09567          if (chan->caller.id.number.valid && chan->caller.id.number.str) {
09568             ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
09569          } else {
09570             ast_verb(3, "Username not entered\n"); 
09571             return -1;
09572          }
09573       } else if (mailbox[0] == '*') {
09574          /* user entered '*' */
09575          if (ast_exists_extension(chan, chan->context, "a", 1,
09576             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09577             return -1;
09578          }
09579          mailbox[0] = '\0';
09580       }
09581 
09582       if (useadsi)
09583          adsi_password(chan);
09584 
09585       if (!ast_strlen_zero(prefix)) {
09586          char fullusername[80] = "";
09587          ast_copy_string(fullusername, prefix, sizeof(fullusername));
09588          strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
09589          ast_copy_string(mailbox, fullusername, mailbox_size);
09590       }
09591 
09592       ast_debug(1, "Before find user for mailbox %s\n", mailbox);
09593       vmu = find_user(&vmus, context, mailbox);
09594       if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
09595          /* saved password is blank, so don't bother asking */
09596          password[0] = '\0';
09597       } else {
09598          if (ast_streamfile(chan, vm_password, chan->language)) {
09599             ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
09600             return -1;
09601          }
09602          if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
09603             ast_log(AST_LOG_WARNING, "Unable to read password\n");
09604             return -1;
09605          } else if (password[0] == '*') {
09606             /* user entered '*' */
09607             if (ast_exists_extension(chan, chan->context, "a", 1,
09608                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09609                mailbox[0] = '*';
09610                return -1;
09611             }
09612             mailbox[0] = '\0';
09613          }
09614       }
09615 
09616       if (vmu) {
09617          passptr = vmu->password;
09618          if (passptr[0] == '-') passptr++;
09619       }
09620       if (vmu && !strcmp(passptr, password))
09621          valid++;
09622       else {
09623          ast_verb(3, "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
09624          if (!ast_strlen_zero(prefix))
09625             mailbox[0] = '\0';
09626       }
09627       logretries++;
09628       if (!valid) {
09629          if (skipuser || logretries >= max_logins) {
09630             if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
09631                ast_log(AST_LOG_WARNING, "Unable to stream incorrect message\n");
09632                return -1;
09633             }
09634          } else {
09635             if (useadsi)
09636                adsi_login(chan);
09637             if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
09638                ast_log(AST_LOG_WARNING, "Unable to stream incorrect mailbox message\n");
09639                return -1;
09640             }
09641          }
09642          if (ast_waitstream(chan, "")) /* Channel is hung up */
09643             return -1;
09644       }
09645    }
09646    if (!valid && (logretries >= max_logins)) {
09647       ast_stopstream(chan);
09648       ast_play_and_wait(chan, "vm-goodbye");
09649       return -1;
09650    }
09651    if (vmu && !skipuser) {
09652       memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
09653    }
09654    return 0;
09655 }

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

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

10705 {
10706    struct ast_vm_user svm;
10707    char *context, *box;
10708    AST_DECLARE_APP_ARGS(args,
10709       AST_APP_ARG(mbox);
10710       AST_APP_ARG(options);
10711    );
10712    static int dep_warning = 0;
10713 
10714    if (ast_strlen_zero(data)) {
10715       ast_log(AST_LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
10716       return -1;
10717    }
10718 
10719    if (!dep_warning) {
10720       dep_warning = 1;
10721       ast_log(AST_LOG_WARNING, "MailboxExists is deprecated.  Please use ${MAILBOX_EXISTS(%s)} instead.\n", (char *) data);
10722    }
10723 
10724    box = ast_strdupa(data);
10725 
10726    AST_STANDARD_APP_ARGS(args, box);
10727 
10728    if (args.options) {
10729    }
10730 
10731    if ((context = strchr(args.mbox, '@'))) {
10732       *context = '\0';
10733       context++;
10734    }
10735 
10736    if (find_user(&svm, context, args.mbox)) {
10737       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
10738    } else
10739       pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
10740 
10741    return 0;
10742 }

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

09521 {
09522    if (!strncasecmp(chan->language, "es", 2)) {         /* SPANISH */
09523       return vm_browse_messages_es(chan, vms, vmu);
09524    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK */
09525       return vm_browse_messages_gr(chan, vms, vmu);
09526    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW */
09527       return vm_browse_messages_he(chan, vms, vmu);
09528    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN */
09529       return vm_browse_messages_it(chan, vms, vmu);
09530    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE */
09531       return vm_browse_messages_pt(chan, vms, vmu);
09532    } else if (!strncasecmp(chan->language, "vi", 2)) {  /* VIETNAMESE */
09533       return vm_browse_messages_vi(chan, vms, vmu);
09534    } else if (!strncasecmp(chan->language, "zh", 2)) {  /* CHINESE (Taiwan) */
09535       return vm_browse_messages_zh(chan, vms, vmu);
09536    } else {                                             /* Default to English syntax */
09537       return vm_browse_messages_en(chan, vms, vmu);
09538    }
09539 }

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

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

09360 {
09361    int cmd = 0;
09362 
09363    if (vms->lastmsg > -1) {
09364       cmd = play_message(chan, vmu, vms);
09365    } else {
09366       cmd = ast_play_and_wait(chan, "vm-youhave");
09367       if (!cmd) 
09368          cmd = ast_play_and_wait(chan, "vm-no");
09369       if (!cmd) {
09370          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09371          cmd = ast_play_and_wait(chan, vms->fn);
09372       }
09373       if (!cmd)
09374          cmd = ast_play_and_wait(chan, "vm-messages");
09375    }
09376    return cmd;
09377 }

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

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

09414 {
09415    int cmd;
09416 
09417    if (vms->lastmsg > -1) {
09418       cmd = play_message(chan, vmu, vms);
09419    } else {
09420       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09421       if (!cmd)
09422          cmd = ast_play_and_wait(chan, "vm-messages");
09423       if (!cmd) {
09424          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09425          cmd = ast_play_and_wait(chan, vms->fn);
09426       }
09427    }
09428    return cmd;
09429 }

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

09308 {
09309    int cmd = 0;
09310 
09311    if (vms->lastmsg > -1) {
09312       cmd = play_message(chan, vmu, vms);
09313    } else {
09314       cmd = ast_play_and_wait(chan, "vm-youhaveno");
09315       if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
09316          if (!cmd) {
09317             snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
09318             cmd = ast_play_and_wait(chan, vms->fn);
09319          }
09320          if (!cmd)
09321             cmd = ast_play_and_wait(chan, "vm-messages");
09322       } else {
09323          if (!cmd)
09324             cmd = ast_play_and_wait(chan, "vm-messages");
09325          if (!cmd) {
09326             snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09327             cmd = ast_play_and_wait(chan, vms->fn);
09328          }
09329       }
09330    } 
09331    return cmd;
09332 }

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

Definition at line 9335 of file app_voicemail_imapstorage.c.

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

09336 {
09337    int cmd = 0;
09338 
09339    if (vms->lastmsg > -1) {
09340       cmd = play_message(chan, vmu, vms);
09341    } else {
09342       if (!strcasecmp(vms->fn, "INBOX")) {
09343          cmd = ast_play_and_wait(chan, "vm-nonewmessages");
09344       } else {
09345          cmd = ast_play_and_wait(chan, "vm-nomessages");
09346       }
09347    }
09348    return cmd;
09349 }

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

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

09388 {
09389    int cmd;
09390 
09391    if (vms->lastmsg > -1) {
09392       cmd = play_message(chan, vmu, vms);
09393    } else {
09394       cmd = ast_play_and_wait(chan, "vm-no");
09395       if (!cmd)
09396          cmd = ast_play_and_wait(chan, "vm-message");
09397       if (!cmd) {
09398          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09399          cmd = ast_play_and_wait(chan, vms->fn);
09400       }
09401    }
09402    return cmd;
09403 }

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

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

09440 {
09441    int cmd;
09442 
09443    if (vms->lastmsg > -1) {
09444       cmd = play_message(chan, vmu, vms);
09445    } else {
09446       cmd = ast_play_and_wait(chan, "vm-no");
09447       if (!cmd) {
09448          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09449          cmd = ast_play_and_wait(chan, vms->fn);
09450       }
09451       if (!cmd)
09452          cmd = ast_play_and_wait(chan, "vm-messages");
09453    }
09454    return cmd;
09455 }

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

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

09494 {
09495    int cmd = 0;
09496 
09497    if (vms->lastmsg > -1) {
09498       cmd = play_message(chan, vmu, vms);
09499    } else {
09500       cmd = ast_play_and_wait(chan, "vm-no");
09501       if (!cmd) {
09502          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09503          cmd = ast_play_and_wait(chan, vms->fn);
09504       }
09505    }
09506    return cmd;
09507 }

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

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

09466 {
09467    int cmd;
09468 
09469    if (vms->lastmsg > -1) {
09470       cmd = play_message(chan, vmu, vms);
09471    } else {
09472       cmd = ast_play_and_wait(chan, "vm-you");
09473       if (!cmd) 
09474          cmd = ast_play_and_wait(chan, "vm-haveno");
09475       if (!cmd)
09476          cmd = ast_play_and_wait(chan, "vm-messages");
09477       if (!cmd) {
09478          snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
09479          cmd = ast_play_and_wait(chan, vms->fn);
09480       }
09481    }
09482    return cmd;
09483 }

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 1439 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_variable_append(), ast_variable_new(), ast_variable_retrieve(), ast_variable_update(), ast_verb, change_password_realtime(), CONFIG_FLAG_WITHCOMMENTS, config_flags, CONFIG_STATUS_FILEINVALID, ast_vm_user::context, ast_vm_user::mailbox, OPT_PWLOC_SPOOLDIR, OPT_PWLOC_USERSCONF, OPT_PWLOC_VOICEMAILCONF, ast_vm_user::password, ast_vm_user::passwordlocation, reset_user_pw(), value, var, VOICEMAIL_CONFIG, and write_password_to_file().

01440 {
01441    struct ast_config   *cfg = NULL;
01442    struct ast_variable *var = NULL;
01443    struct ast_category *cat = NULL;
01444    char *category = NULL, *value = NULL, *new = NULL;
01445    const char *tmp = NULL;
01446    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
01447    char secretfn[PATH_MAX] = "";
01448    int found = 0;
01449 
01450    if (!change_password_realtime(vmu, newpassword))
01451       return;
01452 
01453    /* check if we should store the secret in the spool directory next to the messages */
01454    switch (vmu->passwordlocation) {
01455    case OPT_PWLOC_SPOOLDIR:
01456       snprintf(secretfn, sizeof(secretfn), "%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
01457       if (write_password_to_file(secretfn, newpassword) == 0) {
01458          ast_verb(4, "Writing voicemail password to file %s succeeded\n", secretfn);
01459          reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01460          ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01461          break;
01462       } else {
01463          ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
01464       }
01465       /* Fall-through */
01466    case OPT_PWLOC_VOICEMAILCONF:
01467       if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01468          while ((category = ast_category_browse(cfg, category))) {
01469             if (!strcasecmp(category, vmu->context)) {
01470                if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
01471                   ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
01472                   break;
01473                }
01474                value = strstr(tmp, ",");
01475                if (!value) {
01476                   new = alloca(strlen(newpassword)+1);
01477                   sprintf(new, "%s", newpassword);
01478                } else {
01479                   new = alloca((strlen(value) + strlen(newpassword) + 1));
01480                   sprintf(new, "%s%s", newpassword, value);
01481                }
01482                if (!(cat = ast_category_get(cfg, category))) {
01483                   ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
01484                   break;
01485                }
01486                ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
01487                found = 1;
01488             }
01489          }
01490          /* save the results */
01491          if (found) {
01492             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01493             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01494             ast_config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
01495             break;
01496          }
01497       }
01498       /* Fall-through */
01499    case OPT_PWLOC_USERSCONF:
01500       /* check users.conf and update the password stored for the mailbox */
01501       /* if no vmsecret entry exists create one. */
01502       if ((cfg = ast_config_load("users.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
01503          ast_debug(4, "we are looking for %s\n", vmu->mailbox);
01504          for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
01505             ast_debug(4, "users.conf: %s\n", category);
01506             if (!strcasecmp(category, vmu->mailbox)) {
01507                if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
01508                   ast_debug(3, "looks like we need to make vmsecret!\n");
01509                   var = ast_variable_new("vmsecret", newpassword, "");
01510                } else {
01511                   var = NULL;
01512                }
01513                new = alloca(strlen(newpassword) + 1);
01514                sprintf(new, "%s", newpassword);
01515                if (!(cat = ast_category_get(cfg, category))) {
01516                   ast_debug(4, "failed to get category!\n");
01517                   ast_free(var);
01518                   break;
01519                }
01520                if (!var) {
01521                   ast_variable_update(cat, "vmsecret", new, NULL, 0);
01522                } else {
01523                   ast_variable_append(cat, var);
01524                }
01525                found = 1;
01526                break;
01527             }
01528          }
01529          /* save the results and clean things up */
01530          if (found) {
01531             reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01532             ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01533             ast_config_text_file_save("users.conf", cfg, "AppVoicemail");
01534          }
01535       }
01536    }
01537 }

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

Definition at line 1539 of file app_voicemail_imapstorage.c.

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

01540 {
01541    char buf[255];
01542    snprintf(buf, sizeof(buf), "%s %s %s %s", ext_pass_cmd, vmu->context, vmu->mailbox, newpassword);
01543    if (!ast_safe_system(buf)) {
01544       ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
01545       /* Reset the password in memory, too */
01546       reset_user_pw(vmu->context, vmu->mailbox, newpassword);
01547    }
01548 }

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

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

01131 {
01132    int fds[2], pid = 0;
01133 
01134    memset(buf, 0, len);
01135 
01136    if (pipe(fds)) {
01137       snprintf(buf, len, "FAILURE: Pipe failed: %s", strerror(errno));
01138    } else {
01139       /* good to go*/
01140       pid = ast_safe_fork(0);
01141 
01142       if (pid < 0) {
01143          /* ok maybe not */
01144          close(fds[0]);
01145          close(fds[1]);
01146          snprintf(buf, len, "FAILURE: Fork failed");
01147       } else if (pid) {
01148          /* parent */
01149          close(fds[1]);
01150          if (read(fds[0], buf, len) < 0) {
01151             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
01152          }
01153          close(fds[0]);
01154       } else {
01155          /*  child */
01156          AST_DECLARE_APP_ARGS(arg,
01157             AST_APP_ARG(v)[20];
01158          );
01159          char *mycmd = ast_strdupa(command);
01160 
01161          close(fds[0]);
01162          dup2(fds[1], STDOUT_FILENO);
01163          close(fds[1]);
01164          ast_close_fds_above_n(STDOUT_FILENO);
01165 
01166          AST_NONSTANDARD_APP_ARGS(arg, mycmd, ' ');
01167 
01168          execv(arg.v[0], arg.v); 
01169          printf("FAILURE: %s", strerror(errno));
01170          _exit(0);
01171       }
01172    }
01173    return buf;
01174 }

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

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

04057 {
04058    char *txt;
04059    int txtsize = 0;
04060 
04061    txtsize = (strlen(file) + 5)*sizeof(char);
04062    txt = alloca(txtsize);
04063    /* Sprintf here would safe because we alloca'd exactly the right length,
04064     * but trying to eliminate all sprintf's anyhow
04065     */
04066    if (ast_check_realtime("voicemail_data")) {
04067       ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL);
04068    }
04069    snprintf(txt, txtsize, "%s.txt", file);
04070    unlink(txt);
04071    return ast_filedelete(file, NULL);
04072 }

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

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

10388 {
10389    int res = 0;
10390    char *tmp;
10391    struct leave_vm_options leave_options;
10392    struct ast_flags flags = { 0 };
10393    char *opts[OPT_ARG_ARRAY_SIZE];
10394    AST_DECLARE_APP_ARGS(args,
10395       AST_APP_ARG(argv0);
10396       AST_APP_ARG(argv1);
10397    );
10398    
10399    memset(&leave_options, 0, sizeof(leave_options));
10400 
10401    if (chan->_state != AST_STATE_UP)
10402       ast_answer(chan);
10403 
10404    if (!ast_strlen_zero(data)) {
10405       tmp = ast_strdupa(data);
10406       AST_STANDARD_APP_ARGS(args, tmp);
10407       if (args.argc == 2) {
10408          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
10409             return -1;
10410          ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
10411          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
10412             int gain;
10413 
10414             if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
10415                ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10416                return -1;
10417             } else {
10418                leave_options.record_gain = (signed char) gain;
10419             }
10420          }
10421          if (ast_test_flag(&flags, OPT_DTMFEXIT)) {
10422             if (!ast_strlen_zero(opts[OPT_ARG_DTMFEXIT]))
10423                leave_options.exitcontext = opts[OPT_ARG_DTMFEXIT];
10424          }
10425       }
10426    } else {
10427       char temp[256];
10428       res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0);
10429       if (res < 0)
10430          return res;
10431       if (ast_strlen_zero(temp))
10432          return 0;
10433       args.argv0 = ast_strdupa(temp);
10434    }
10435 
10436    res = leave_voicemail(chan, args.argv0, &leave_options);
10437    if (res == 't') {
10438       ast_play_and_wait(chan, "vm-goodbye");
10439       res = 0;
10440    }
10441 
10442    if (res == OPERATOR_EXIT) {
10443       res = 0;
10444    }
10445 
10446    if (res == ERROR_LOCK_PATH) {
10447       ast_log(AST_LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
10448       pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
10449       res = 0;
10450    }
10451 
10452    return res;
10453 }

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

Definition at line 9657 of file app_voicemail_imapstorage.c.

References ast_channel::_state, adsi_begin(), adsi_delete(), adsi_folders(), adsi_goodbye(), adsi_message(), adsi_status(), adsi_status2(), advanced_options(), args, ast_adsi_unload_session(), ast_answer(), AST_APP_ARG, ast_app_inboxcount2(), ast_app_parse_options(), ast_calloc, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, ast_goto_if_exists(), ast_log(), AST_LOG_ERROR, ast_manager_event, ast_mutex_lock, ast_mutex_unlock, ast_play_and_wait(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_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(), 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, and VM_SVMAIL.

09658 {
09659    /* XXX This is, admittedly, some pretty horrendous code.  For some
09660       reason it just seemed a lot easier to do with GOTO's.  I feel
09661       like I'm back in my GWBASIC days. XXX */
09662    int res = -1;
09663    int cmd = 0;
09664    int valid = 0;
09665    char prefixstr[80] ="";
09666    char ext_context[256]="";
09667    int box;
09668    int useadsi = 0;
09669    int skipuser = 0;
09670    struct vm_state vms;
09671    struct ast_vm_user *vmu = NULL, vmus;
09672    char *context = NULL;
09673    int silentexit = 0;
09674    struct ast_flags flags = { 0 };
09675    signed char record_gain = 0;
09676    int play_auto = 0;
09677    int play_folder = 0;
09678    int in_urgent = 0;
09679 #ifdef IMAP_STORAGE
09680    int deleted = 0;
09681 #endif
09682 
09683    /* Add the vm_state to the active list and keep it active */
09684    memset(&vms, 0, sizeof(vms));
09685 
09686    vms.lastmsg = -1;
09687 
09688    memset(&vmus, 0, sizeof(vmus));
09689 
09690    if (chan->_state != AST_STATE_UP) {
09691       ast_debug(1, "Before ast_answer\n");
09692       ast_answer(chan);
09693    }
09694 
09695    if (!ast_strlen_zero(data)) {
09696       char *opts[OPT_ARG_ARRAY_SIZE];
09697       char *parse;
09698       AST_DECLARE_APP_ARGS(args,
09699          AST_APP_ARG(argv0);
09700          AST_APP_ARG(argv1);
09701       );
09702 
09703       parse = ast_strdupa(data);
09704 
09705       AST_STANDARD_APP_ARGS(args, parse);
09706 
09707       if (args.argc == 2) {
09708          if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
09709             return -1;
09710          if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
09711             int gain;
09712             if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
09713                if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) {
09714                   ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
09715                   return -1;
09716                } else {
09717                   record_gain = (signed char) gain;
09718                }
09719             } else {
09720                ast_log(AST_LOG_WARNING, "Invalid Gain level set with option g\n");
09721             }
09722          }
09723          if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
09724             play_auto = 1;
09725             if (!ast_strlen_zero(opts[OPT_ARG_PLAYFOLDER])) {
09726                /* See if it is a folder name first */
09727                if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
09728                   if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%30d", &play_folder) != 1) {
09729                      play_folder = -1;
09730                   }
09731                } else {
09732                   play_folder = get_folder_by_name(opts[OPT_ARG_PLAYFOLDER]);
09733                }
09734             } else {
09735                ast_log(AST_LOG_WARNING, "Invalid folder set with option a\n");
09736             }
09737             if (play_folder > 9 || play_folder < 0) {
09738                ast_log(AST_LOG_WARNING,
09739                   "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
09740                   opts[OPT_ARG_PLAYFOLDER]);
09741                play_folder = 0;
09742             }
09743          }
09744       } else {
09745          /* old style options parsing */
09746          while (*(args.argv0)) {
09747             if (*(args.argv0) == 's')
09748                ast_set_flag(&flags, OPT_SILENT);
09749             else if (*(args.argv0) == 'p')
09750                ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
09751             else 
09752                break;
09753             (args.argv0)++;
09754          }
09755 
09756       }
09757 
09758       valid = ast_test_flag(&flags, OPT_SILENT);
09759 
09760       if ((context = strchr(args.argv0, '@')))
09761          *context++ = '\0';
09762 
09763       if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
09764          ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
09765       else
09766          ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
09767 
09768       if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
09769          skipuser++;
09770       else
09771          valid = 0;
09772    }
09773 
09774    if (!valid)
09775       res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
09776 
09777    ast_debug(1, "After vm_authenticate\n");
09778 
09779    if (vms.username[0] == '*') {
09780       ast_debug(1, "user pressed * in context '%s'\n", chan->context);
09781 
09782       /* user entered '*' */
09783       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
09784          res = 0; /* prevent hangup */
09785          goto out;
09786       }
09787    }
09788 
09789    if (!res) {
09790       valid = 1;
09791       if (!skipuser)
09792          vmu = &vmus;
09793    } else {
09794       res = 0;
09795    }
09796 
09797    /* If ADSI is supported, setup login screen */
09798    adsi_begin(chan, &useadsi);
09799 
09800    if (!valid) {
09801       goto out;
09802    }
09803 
09804 #ifdef IMAP_STORAGE
09805    pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
09806    pthread_setspecific(ts_vmstate.key, &vms);
09807 
09808    vms.interactive = 1;
09809    vms.updated = 1;
09810    if (vmu)
09811       ast_copy_string(vms.context, vmu->context, sizeof(vms.context));
09812    vmstate_insert(&vms);
09813    init_vm_state(&vms);
09814 #endif
09815    /* Avoid allocating a buffer of 0 bytes, because some platforms really don't like that. */
09816    if (!(vms.deleted = ast_calloc(vmu->maxmsg ? vmu->maxmsg : 1, sizeof(int)))) {
09817       ast_log(AST_LOG_ERROR, "Could not allocate memory for deleted message storage!\n");
09818       cmd = ast_play_and_wait(chan, "an-error-has-occured");
09819       return -1;
09820    }
09821    if (!(vms.heard = ast_calloc(vmu->maxmsg ? vmu->maxmsg : 1, sizeof(int)))) {
09822       ast_log(AST_LOG_ERROR, "Could not allocate memory for heard message storage!\n");
09823       cmd = ast_play_and_wait(chan, "an-error-has-occured");
09824       return -1;
09825    }
09826    
09827    /* Set language from config to override channel language */
09828    if (!ast_strlen_zero(vmu->language))
09829       ast_string_field_set(chan, language, vmu->language);
09830 
09831    /* Retrieve urgent, old and new message counts */
09832    ast_debug(1, "Before open_mailbox\n");
09833    res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
09834    if (res < 0)
09835       goto out;
09836    vms.oldmessages = vms.lastmsg + 1;
09837    ast_debug(1, "Number of old messages: %d\n", vms.oldmessages);
09838    /* check INBOX */
09839    res = open_mailbox(&vms, vmu, NEW_FOLDER);
09840    if (res < 0)
09841       goto out;
09842    vms.newmessages = vms.lastmsg + 1;
09843    ast_debug(1, "Number of new messages: %d\n", vms.newmessages);
09844    /* Start in Urgent */
09845    in_urgent = 1;
09846    res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */
09847    if (res < 0)
09848       goto out;
09849    vms.urgentmessages = vms.lastmsg + 1;
09850    ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages);
09851 
09852    /* Select proper mailbox FIRST!! */
09853    if (play_auto) {
09854       if (vms.urgentmessages) {
09855          in_urgent = 1;
09856          res = open_mailbox(&vms, vmu, 11);
09857       } else {
09858          in_urgent = 0;
09859          res = open_mailbox(&vms, vmu, play_folder);
09860       }
09861       if (res < 0)
09862          goto out;
09863 
09864       /* If there are no new messages, inform the user and hangup */
09865       if (vms.lastmsg == -1) {
09866          in_urgent = 0;
09867          cmd = vm_browse_messages(chan, &vms, vmu);
09868          res = 0;
09869          goto out;
09870       }
09871    } else {
09872       if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) {
09873          /* If we only have old messages start here */
09874          res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */
09875          in_urgent = 0;
09876          play_folder = 1;
09877          if (res < 0)
09878             goto out;
09879       } else if (!vms.urgentmessages && vms.newmessages) {
09880          /* If we have new messages but none are urgent */
09881          in_urgent = 0;
09882          res = open_mailbox(&vms, vmu, NEW_FOLDER);
09883          if (res < 0)
09884             goto out;
09885       }
09886    }
09887 
09888    if (useadsi)
09889       adsi_status(chan, &vms);
09890    res = 0;
09891 
09892    /* Check to see if this is a new user */
09893    if (!strcasecmp(vmu->mailbox, vmu->password) && 
09894       (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
09895       if (ast_play_and_wait(chan, "vm-newuser") == -1)
09896          ast_log(AST_LOG_WARNING, "Couldn't stream new user file\n");
09897       cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
09898       if ((cmd == 't') || (cmd == '#')) {
09899          /* Timeout */
09900          res = 0;
09901          goto out;
09902       } else if (cmd < 0) {
09903          /* Hangup */
09904          res = -1;
09905          goto out;
09906       }
09907    }
09908 #ifdef IMAP_STORAGE
09909       ast_debug(3, "Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
09910       if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
09911          ast_debug(1, "*** QUOTA EXCEEDED!!\n");
09912          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09913       }
09914       ast_debug(3, "Checking quotas: User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
09915       if ((vms.newmessages + vms.oldmessages) >= vmu->maxmsg) {
09916          ast_log(AST_LOG_WARNING, "No more messages possible.  User has %d messages and limit is %d.\n", (vms.newmessages + vms.oldmessages), vmu->maxmsg);
09917          cmd = ast_play_and_wait(chan, "vm-mailboxfull");
09918       }
09919 #endif
09920    if (play_auto) {
09921       cmd = '1';
09922    } else {
09923       cmd = vm_intro(chan, vmu, &vms);
09924    }
09925 
09926    vms.repeats = 0;
09927    vms.starting = 1;
09928    while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09929       /* Run main menu */
09930       switch (cmd) {
09931       case '1': /* First message */
09932          vms.curmsg = 0;
09933          /* Fall through */
09934       case '5': /* Play current message */
09935          cmd = vm_browse_messages(chan, &vms, vmu);
09936          break;
09937       case '2': /* Change folders */
09938          if (useadsi)
09939             adsi_folders(chan, 0, "Change to folder...");
09940          cmd = get_folder2(chan, "vm-changeto", 0);
09941          if (cmd == '#') {
09942             cmd = 0;
09943          } else if (cmd > 0) {
09944             cmd = cmd - '0';
09945             res = close_mailbox(&vms, vmu);
09946             if (res == ERROR_LOCK_PATH)
09947                goto out;
09948             /* If folder is not urgent, set in_urgent to zero! */
09949             if (cmd != 11) in_urgent = 0;
09950             res = open_mailbox(&vms, vmu, cmd);
09951             if (res < 0)
09952                goto out;
09953             play_folder = cmd;
09954             cmd = 0;
09955          }
09956          if (useadsi)
09957             adsi_status2(chan, &vms);
09958             
09959          if (!cmd)
09960             cmd = vm_play_folder_name(chan, vms.vmbox);
09961 
09962          vms.starting = 1;
09963          break;
09964       case '3': /* Advanced options */
09965          cmd = 0;
09966          vms.repeats = 0;
09967          while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
09968             switch (cmd) {
09969             case '1': /* Reply */
09970                if (vms.lastmsg > -1 && !vms.starting) {
09971                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
09972                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
09973                      res = cmd;
09974                      goto out;
09975                   }
09976                } else
09977                   cmd = ast_play_and_wait(chan, "vm-sorry");
09978                cmd = 't';
09979                break;
09980             case '2': /* Callback */
09981                if (!vms.starting)
09982                   ast_verb(3, "Callback Requested\n");
09983                if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
09984                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
09985                   if (cmd == 9) {
09986                      silentexit = 1;
09987                      goto out;
09988                   } else if (cmd == ERROR_LOCK_PATH) {
09989                      res = cmd;
09990                      goto out;
09991                   }
09992                } else 
09993                   cmd = ast_play_and_wait(chan, "vm-sorry");
09994                cmd = 't';
09995                break;
09996             case '3': /* Envelope */
09997                if (vms.lastmsg > -1 && !vms.starting) {
09998                   cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
09999                   if (cmd == ERROR_LOCK_PATH) {
10000                      res = cmd;
10001                      goto out;
10002                   }
10003                } else
10004                   cmd = ast_play_and_wait(chan, "vm-sorry");
10005                cmd = 't';
10006                break;
10007             case '4': /* Dialout */
10008                if (!ast_strlen_zero(vmu->dialout)) {
10009                   cmd = dialout(chan, vmu, NULL, vmu->dialout);
10010                   if (cmd == 9) {
10011                      silentexit = 1;
10012                      goto out;
10013                   }
10014                } else 
10015                   cmd = ast_play_and_wait(chan, "vm-sorry");
10016                cmd = 't';
10017                break;
10018 
10019             case '5': /* Leave VoiceMail */
10020                if (ast_test_flag(vmu, VM_SVMAIL)) {
10021                   cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
10022                   if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) {
10023                      res = cmd;
10024                      goto out;
10025                   }
10026                } else
10027                   cmd = ast_play_and_wait(chan, "vm-sorry");
10028                cmd = 't';
10029                break;
10030                
10031             case '*': /* Return to main menu */
10032                cmd = 't';
10033                break;
10034 
10035             default:
10036                cmd = 0;
10037                if (!vms.starting) {
10038                   cmd = ast_play_and_wait(chan, "vm-toreply");
10039                }
10040                if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
10041                   cmd = ast_play_and_wait(chan, "vm-tocallback");
10042                }
10043                if (!cmd && !vms.starting) {
10044                   cmd = ast_play_and_wait(chan, "vm-tohearenv");
10045                }
10046                if (!ast_strlen_zero(vmu->dialout) && !cmd) {
10047                   cmd = ast_play_and_wait(chan, "vm-tomakecall");
10048                }
10049                if (ast_test_flag(vmu, VM_SVMAIL) && !cmd)
10050                   cmd = ast_play_and_wait(chan, "vm-leavemsg");
10051                if (!cmd)
10052                   cmd = ast_play_and_wait(chan, "vm-starmain");
10053                if (!cmd)
10054                   cmd = ast_waitfordigit(chan, 6000);
10055                if (!cmd)
10056                   vms.repeats++;
10057                if (vms.repeats > 3)
10058                   cmd = 't';
10059             }
10060          }
10061          if (cmd == 't') {
10062             cmd = 0;
10063             vms.repeats = 0;
10064          }
10065          break;
10066       case '4': /* Go to the previous message */
10067          if (vms.curmsg > 0) {
10068             vms.curmsg--;
10069             cmd = play_message(chan, vmu, &vms);
10070          } else {
10071             /* Check if we were listening to new
10072                messages.  If so, go to Urgent messages
10073                instead of saying "no more messages"
10074             */
10075             if (in_urgent == 0 && vms.urgentmessages > 0) {
10076                /* Check for Urgent messages */
10077                in_urgent = 1;
10078                res = close_mailbox(&vms, vmu);
10079                if (res == ERROR_LOCK_PATH)
10080                   goto out;
10081                res = open_mailbox(&vms, vmu, 11);  /* Open Urgent folder */
10082                if (res < 0)
10083                   goto out;
10084                ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1);
10085                vms.curmsg = vms.lastmsg;
10086                if (vms.lastmsg < 0)
10087                   cmd = ast_play_and_wait(chan, "vm-nomore");
10088             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10089                vms.curmsg = vms.lastmsg;
10090                cmd = play_message(chan, vmu, &vms);
10091             } else {
10092                cmd = ast_play_and_wait(chan, "vm-nomore");
10093             }
10094          }
10095          break;
10096       case '6': /* Go to the next message */
10097          if (vms.curmsg < vms.lastmsg) {
10098             vms.curmsg++;
10099             cmd = play_message(chan, vmu, &vms);
10100          } else {
10101             if (in_urgent && vms.newmessages > 0) {
10102                /* Check if we were listening to urgent
10103                 * messages.  If so, go to regular new messages
10104                 * instead of saying "no more messages"
10105                 */
10106                in_urgent = 0;
10107                res = close_mailbox(&vms, vmu);
10108                if (res == ERROR_LOCK_PATH)
10109                   goto out;
10110                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10111                if (res < 0)
10112                   goto out;
10113                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10114                vms.curmsg = -1;
10115                if (vms.lastmsg < 0) {
10116                   cmd = ast_play_and_wait(chan, "vm-nomore");
10117                }
10118             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10119                vms.curmsg = 0;
10120                cmd = play_message(chan, vmu, &vms);
10121             } else {
10122                cmd = ast_play_and_wait(chan, "vm-nomore");
10123             }
10124          }
10125          break;
10126       case '7': /* Delete the current message */
10127          if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
10128             vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
10129             if (useadsi)
10130                adsi_delete(chan, &vms);
10131             if (vms.deleted[vms.curmsg]) {
10132                if (play_folder == 0) {
10133                   if (in_urgent) {
10134                      vms.urgentmessages--;
10135                   } else {
10136                      vms.newmessages--;
10137                   }
10138                }
10139                else if (play_folder == 1)
10140                   vms.oldmessages--;
10141                cmd = ast_play_and_wait(chan, "vm-deleted");
10142             } else {
10143                if (play_folder == 0) {
10144                   if (in_urgent) {
10145                      vms.urgentmessages++;
10146                   } else {
10147                      vms.newmessages++;
10148                   }
10149                }
10150                else if (play_folder == 1)
10151                   vms.oldmessages++;
10152                cmd = ast_play_and_wait(chan, "vm-undeleted");
10153             }
10154             if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
10155                if (vms.curmsg < vms.lastmsg) {
10156                   vms.curmsg++;
10157                   cmd = play_message(chan, vmu, &vms);
10158                } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10159                   vms.curmsg = 0;
10160                   cmd = play_message(chan, vmu, &vms);
10161                } else {
10162                   /* Check if we were listening to urgent
10163                      messages.  If so, go to regular new messages
10164                      instead of saying "no more messages"
10165                   */
10166                   if (in_urgent == 1) {
10167                      /* Check for new messages */
10168                      in_urgent = 0;
10169                      res = close_mailbox(&vms, vmu);
10170                      if (res == ERROR_LOCK_PATH)
10171                         goto out;
10172                      res = open_mailbox(&vms, vmu, NEW_FOLDER);
10173                      if (res < 0)
10174                         goto out;
10175                      ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10176                      vms.curmsg = -1;
10177                      if (vms.lastmsg < 0)
10178                         cmd = ast_play_and_wait(chan, "vm-nomore");
10179                   } else {
10180                      cmd = ast_play_and_wait(chan, "vm-nomore");
10181                   }
10182                }
10183             }
10184          } else /* Delete not valid if we haven't selected a message */
10185             cmd = 0;
10186 #ifdef IMAP_STORAGE
10187          deleted = 1;
10188 #endif
10189          break;
10190    
10191       case '8': /* Forward the current messgae */
10192          if (vms.lastmsg > -1) {
10193             cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
10194             if (cmd == ERROR_LOCK_PATH) {
10195                res = cmd;
10196                goto out;
10197             }
10198          } else {
10199             /* Check if we were listening to urgent
10200                messages.  If so, go to regular new messages
10201                instead of saying "no more messages"
10202             */
10203             if (in_urgent == 1 && vms.newmessages > 0) {
10204                /* Check for new messages */
10205                in_urgent = 0;
10206                res = close_mailbox(&vms, vmu);
10207                if (res == ERROR_LOCK_PATH)
10208                   goto out;
10209                res = open_mailbox(&vms, vmu, NEW_FOLDER);
10210                if (res < 0)
10211                   goto out;
10212                ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10213                vms.curmsg = -1;
10214                if (vms.lastmsg < 0)
10215                   cmd = ast_play_and_wait(chan, "vm-nomore");
10216             } else {
10217                cmd = ast_play_and_wait(chan, "vm-nomore");
10218             }
10219          }
10220          break;
10221       case '9': /* Save message to folder */
10222          if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
10223             /* No message selected */
10224             cmd = 0;
10225             break;
10226          }
10227          if (useadsi)
10228             adsi_folders(chan, 1, "Save to folder...");
10229          cmd = get_folder2(chan, "vm-savefolder", 1);
10230          box = 0; /* Shut up compiler */
10231          if (cmd == '#') {
10232             cmd = 0;
10233             break;
10234          } else if (cmd > 0) {
10235             box = cmd = cmd - '0';
10236             cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
10237             if (cmd == ERROR_LOCK_PATH) {
10238                res = cmd;
10239                goto out;
10240 #ifndef IMAP_STORAGE
10241             } else if (!cmd) {
10242                vms.deleted[vms.curmsg] = 1;
10243 #endif
10244             } else {
10245                vms.deleted[vms.curmsg] = 0;
10246                vms.heard[vms.curmsg] = 0;
10247             }
10248          }
10249          make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
10250          if (useadsi)
10251             adsi_message(chan, &vms);
10252          snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(vmu, box));
10253          if (!cmd) {
10254             cmd = ast_play_and_wait(chan, "vm-message");
10255             if (!cmd) 
10256                cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
10257             if (!cmd)
10258                cmd = ast_play_and_wait(chan, "vm-savedto");
10259             if (!cmd)
10260                cmd = vm_play_folder_name(chan, vms.fn);
10261          } else {
10262             cmd = ast_play_and_wait(chan, "vm-mailboxfull");
10263          }
10264          if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
10265             if (vms.curmsg < vms.lastmsg) {
10266                vms.curmsg++;
10267                cmd = play_message(chan, vmu, &vms);
10268             } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) {
10269                vms.curmsg = 0;
10270                cmd = play_message(chan, vmu, &vms);
10271             } else {
10272                /* Check if we were listening to urgent
10273                   messages.  If so, go to regular new messages
10274                   instead of saying "no more messages"
10275                */
10276                if (in_urgent == 1 && vms.newmessages > 0) {
10277                   /* Check for new messages */
10278                   in_urgent = 0;
10279                   res = close_mailbox(&vms, vmu);
10280                   if (res == ERROR_LOCK_PATH)
10281                      goto out;
10282                   res = open_mailbox(&vms, vmu, NEW_FOLDER);
10283                   if (res < 0)
10284                      goto out;
10285                   ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1);
10286                   vms.curmsg = -1;
10287                   if (vms.lastmsg < 0)
10288                      cmd = ast_play_and_wait(chan, "vm-nomore");
10289                } else {
10290                   cmd = ast_play_and_wait(chan, "vm-nomore");
10291                }
10292             }
10293          }
10294          break;
10295       case '*': /* Help */
10296          if (!vms.starting) {
10297             cmd = ast_play_and_wait(chan, "vm-onefor");
10298             if (!strncasecmp(chan->language, "he", 2)) {
10299                cmd = ast_play_and_wait(chan, "vm-for");
10300             }
10301             if (!cmd)
10302                cmd = vm_play_folder_name(chan, vms.vmbox);
10303             if (!cmd)
10304                cmd = ast_play_and_wait(chan, "vm-opts");
10305             if (!cmd)
10306                cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
10307          } else
10308             cmd = 0;
10309          break;
10310       case '0': /* Mailbox options */
10311          cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
10312          if (useadsi)
10313             adsi_status(chan, &vms);
10314          break;
10315       default: /* Nothing */
10316          cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
10317          break;
10318       }
10319    }
10320    if ((cmd == 't') || (cmd == '#')) {
10321       /* Timeout */
10322       res = 0;
10323    } else {
10324       /* Hangup */
10325       res = -1;
10326    }
10327 
10328 out:
10329    if (res > -1) {
10330       ast_stopstream(chan);
10331       adsi_goodbye(chan);
10332       if (valid && res != OPERATOR_EXIT) {
10333          if (silentexit)
10334             res = ast_play_and_wait(chan, "vm-dialout");
10335          else 
10336             res = ast_play_and_wait(chan, "vm-goodbye");
10337       }
10338       if ((valid && res > 0) || res == OPERATOR_EXIT) {
10339          res = 0;
10340       }
10341       if (useadsi)
10342          ast_adsi_unload_session(chan);
10343    }
10344    if (vmu)
10345       close_mailbox(&vms, vmu);
10346    if (valid) {
10347       int new = 0, old = 0, urgent = 0;
10348       snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
10349       ast_manager_event(chan, EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
10350       /* Urgent flag not passwd to externnotify here */
10351       run_externnotify(vmu->context, vmu->mailbox, NULL);
10352       ast_app_inboxcount2(ext_context, &urgent, &new, &old);
10353       queue_mwi_event(ext_context, urgent, new, old);
10354    }
10355 #ifdef IMAP_STORAGE
10356    /* expunge message - use UID Expunge if supported on IMAP server*/
10357    ast_debug(3, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
10358    if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
10359       ast_mutex_lock(&vms.lock);
10360 #ifdef HAVE_IMAP_TK2006
10361       if (LEVELUIDPLUS (vms.mailstream)) {
10362          mail_expunge_full(vms.mailstream, NIL, EX_UID);
10363       } else 
10364 #endif
10365          mail_expunge(vms.mailstream);
10366       ast_mutex_unlock(&vms.lock);
10367    }
10368    /*  before we delete the state, we should copy pertinent info
10369     *  back to the persistent model */
10370    if (vmu) {
10371       vmstate_delete(&vms);
10372    }
10373 #endif
10374    if (vmu)
10375       free_user(vmu);
10376    if (vms.deleted)
10377       ast_free(vms.deleted);
10378    if (vms.heard)
10379       ast_free(vms.heard);
10380 
10381 #ifdef IMAP_STORAGE
10382    pthread_setspecific(ts_vmstate.key, NULL);
10383 #endif
10384    return res;
10385 }

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 6694 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_variable_retrieve(), ast_variable_update(), ast_waitfordigit(), CONFIG_FLAG_NOCACHE, config_flags, CONFIG_STATUS_FILEINVALID, copy(), INTRO, make_file(), ast_vm_user::maxsecs, and play_record_review().

06696 {
06697 #ifdef IMAP_STORAGE
06698    int res;
06699 #endif
06700    int cmd = 0;
06701    int retries = 0, prepend_duration = 0, already_recorded = 0;
06702    char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
06703    char textfile[PATH_MAX];
06704    struct ast_config *msg_cfg;
06705    struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
06706 #ifndef IMAP_STORAGE
06707    signed char zero_gain = 0;
06708 #endif
06709    const char *duration_str;
06710 
06711    /* Must always populate duration correctly */
06712    make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06713    strcpy(textfile, msgfile);
06714    strcpy(backup, msgfile);
06715    strcpy(backup_textfile, msgfile);
06716    strncat(textfile, ".txt", sizeof(textfile) - strlen(textfile) - 1);
06717    strncat(backup, "-bak", sizeof(backup) - strlen(backup) - 1);
06718    strncat(backup_textfile, "-bak.txt", sizeof(backup_textfile) - strlen(backup_textfile) - 1);
06719 
06720    if ((msg_cfg = ast_config_load(textfile, config_flags)) && msg_cfg != CONFIG_STATUS_FILEINVALID && (duration_str = ast_variable_retrieve(msg_cfg, "message", "duration"))) {
06721       *duration = atoi(duration_str);
06722    } else {
06723       *duration = 0;
06724    }
06725 
06726    while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
06727       if (cmd)
06728          retries = 0;
06729       switch (cmd) {
06730       case '1': 
06731 
06732 #ifdef IMAP_STORAGE
06733          /* Record new intro file */
06734          make_file(vms->introfn, sizeof(vms->introfn), curdir, curmsg);
06735          strncat(vms->introfn, "intro", sizeof(vms->introfn));
06736          res = ast_play_and_wait(chan, INTRO);
06737          res = ast_play_and_wait(chan, "beep");
06738          res = play_record_review(chan, NULL, vms->introfn, vmu->maxsecs, vm_fmts, 1, vmu, (int *) duration, NULL, record_gain, vms, flag);
06739          cmd = 't';
06740 #else
06741 
06742          /* prepend a message to the current message, update the metadata and return */
06743 
06744          make_file(msgfile, sizeof(msgfile), curdir, curmsg);
06745          strcpy(textfile, msgfile);
06746          strncat(textfile, ".txt", sizeof(textfile) - 1);
06747          *duration = 0;
06748 
06749          /* if we can't read the message metadata, stop now */
06750          if (!msg_cfg) {
06751             cmd = 0;
06752             break;
06753          }
06754          
06755          /* Back up the original file, so we can retry the prepend and restore it after forward. */
06756 #ifndef IMAP_STORAGE
06757          if (already_recorded) {
06758             ast_filecopy(backup, msgfile, NULL);
06759             copy(backup_textfile, textfile);
06760          }
06761          else {
06762             ast_filecopy(msgfile, backup, NULL);
06763             copy(textfile, backup_textfile);
06764          }
06765 #endif
06766          already_recorded = 1;
06767 
06768          if (record_gain)
06769             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06770 
06771          cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, 1, silencethreshold, maxsilence);
06772          if (cmd == 'S') {
06773             ast_filerename(backup, msgfile, NULL);
06774          }
06775 
06776          if (record_gain)
06777             ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06778 
06779          
06780          if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
06781             *duration = atoi(duration_str);
06782 
06783          if (prepend_duration) {
06784             struct ast_category *msg_cat;
06785             /* need enough space for a maximum-length message duration */
06786             char duration_buf[12];
06787 
06788             *duration += prepend_duration;
06789             msg_cat = ast_category_get(msg_cfg, "message");
06790             snprintf(duration_buf, 11, "%ld", *duration);
06791             if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) {
06792                ast_config_text_file_save(textfile, msg_cfg, "app_voicemail");
06793             }
06794          }
06795 
06796 #endif
06797          break;
06798       case '2': 
06799          /* NULL out introfile so we know there is no intro! */
06800 #ifdef IMAP_STORAGE
06801          *vms->introfn = '\0';
06802 #endif
06803          cmd = 't';
06804          break;
06805       case '*':
06806          cmd = '*';
06807          break;
06808       default: 
06809          cmd = ast_play_and_wait(chan, "vm-forwardoptions");
06810             /* "Press 1 to prepend a message or 2 to forward the message without prepending" */
06811          if (!cmd)
06812             cmd = ast_play_and_wait(chan, "vm-starmain");
06813             /* "press star to return to the main menu" */
06814          if (!cmd)
06815             cmd = ast_waitfordigit(chan, 6000);
06816          if (!cmd)
06817             retries++;
06818          if (retries > 3)
06819             cmd = 't';
06820       }
06821    }
06822 
06823    if (msg_cfg)
06824       ast_config_destroy(msg_cfg);
06825    if (prepend_duration)
06826       *duration = prepend_duration;
06827 
06828    if (already_recorded && cmd == -1) {
06829       /* restore original message if prepention cancelled */
06830       ast_filerename(backup, msgfile, NULL);
06831       rename(backup_textfile, textfile);
06832    }
06833 
06834    if (cmd == 't' || cmd == 'S')
06835       cmd = 0;
06836    return cmd;
06837 }

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

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

08999 {
09000    if (vms->starting && !strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
09001       return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
09002    } else {             /* Default to ENGLISH */
09003       return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
09004    }
09005 }

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

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

08898 {
08899    int res = 0;
08900    /* Play instructions and wait for new command */
08901    while (!res) {
08902       if (vms->starting) {
08903          if (vms->lastmsg > -1) {
08904             if (skipadvanced)
08905                res = ast_play_and_wait(chan, "vm-onefor-full");
08906             else
08907                res = ast_play_and_wait(chan, "vm-onefor");
08908             if (!res)
08909                res = vm_play_folder_name(chan, vms->vmbox);
08910          }
08911          if (!res) {
08912             if (skipadvanced)
08913                res = ast_play_and_wait(chan, "vm-opts-full");
08914             else
08915                res = ast_play_and_wait(chan, "vm-opts");
08916          }
08917       } else {
08918          /* Added for additional help */
08919          if (skipadvanced) {
08920             res = ast_play_and_wait(chan, "vm-onefor-full");
08921             if (!res)
08922                res = vm_play_folder_name(chan, vms->vmbox);
08923             res = ast_play_and_wait(chan, "vm-opts-full");
08924          }
08925          /* Logic:
08926           * If the current message is not the first OR
08927           * if we're listening to the first new message and there are
08928           * also urgent messages, then prompt for navigation to the
08929           * previous message
08930           */
08931          if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
08932             res = ast_play_and_wait(chan, "vm-prev");
08933          }
08934          if (!res && !skipadvanced)
08935             res = ast_play_and_wait(chan, "vm-advopts");
08936          if (!res)
08937             res = ast_play_and_wait(chan, "vm-repeat");
08938          /* Logic:
08939           * If we're not listening to the last message OR
08940           * we're listening to the last urgent message and there are
08941           * also new non-urgent messages, then prompt for navigation
08942           * to the next message
08943           */
08944          if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
08945             (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
08946             res = ast_play_and_wait(chan, "vm-next");
08947          }
08948          if (!res) {
08949             if (!vms->deleted[vms->curmsg])
08950                res = ast_play_and_wait(chan, "vm-delete");
08951             else
08952                res = ast_play_and_wait(chan, "vm-undelete");
08953             if (!res)
08954                res = ast_play_and_wait(chan, "vm-toforward");
08955             if (!res)
08956                res = ast_play_and_wait(chan, "vm-savemessage");
08957          }
08958       }
08959       if (!res) {
08960          res = ast_play_and_wait(chan, "vm-helpexit");
08961       }
08962       if (!res)
08963          res = ast_waitfordigit(chan, 6000);
08964       if (!res) {
08965          vms->repeats++;
08966          if (vms->repeats > 2) {
08967             res = 't';
08968          }
08969       }
08970    }
08971    return res;
08972 }

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

08975 {
08976    int res = 0;
08977    /* Play instructions and wait for new command */
08978    while (!res) {
08979       if (vms->lastmsg > -1) {
08980          res = ast_play_and_wait(chan, "vm-listen");
08981          if (!res)
08982             res = vm_play_folder_name(chan, vms->vmbox);
08983          if (!res)
08984             res = ast_play_and_wait(chan, "press");
08985          if (!res)
08986             res = ast_play_and_wait(chan, "digits/1");
08987       }
08988       if (!res)
08989          res = ast_play_and_wait(chan, "vm-opts");
08990       if (!res) {
08991          vms->starting = 0;
08992          return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
08993       }
08994    }
08995    return res;
08996 }

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

Definition at line 8835 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(), and VM_TEMPGREETWARN.

08836 {
08837    char prefile[256];
08838    
08839    /* Notify the user that the temp greeting is set and give them the option to remove it */
08840    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
08841    if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
08842       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
08843       if (ast_fileexists(prefile, NULL, NULL) > 0) {
08844          ast_play_and_wait(chan, "vm-tempgreetactive");
08845       }
08846       DISPOSE(prefile, -1);
08847    }
08848 
08849    /* Play voicemail intro - syntax is different for different languages */
08850    if (0) {
08851       return 0;
08852    } else if (!strncasecmp(chan->language, "cs", 2)) {  /* CZECH syntax */
08853       return vm_intro_cs(chan, vms);
08854    } else if (!strncasecmp(chan->language, "cz", 2)) {  /* deprecated CZECH syntax */
08855       static int deprecation_warning = 0;
08856       if (deprecation_warning++ % 10 == 0) {
08857          ast_log(LOG_WARNING, "cz is not a standard language code.  Please switch to using cs instead.\n");
08858       }
08859       return vm_intro_cs(chan, vms);
08860    } else if (!strncasecmp(chan->language, "de", 2)) {  /* GERMAN syntax */
08861       return vm_intro_de(chan, vms);
08862    } else if (!strncasecmp(chan->language, "es", 2)) {  /* SPANISH syntax */
08863       return vm_intro_es(chan, vms);
08864    } else if (!strncasecmp(chan->language, "fr", 2)) {  /* FRENCH syntax */
08865       return vm_intro_fr(chan, vms);
08866    } else if (!strncasecmp(chan->language, "gr", 2)) {  /* GREEK syntax */
08867       return vm_intro_gr(chan, vms);
08868    } else if (!strncasecmp(chan->language, "he", 2)) {  /* HEBREW syntax */
08869       return vm_intro_he(chan, vms);
08870    } else if (!strncasecmp(chan->language, "it", 2)) {  /* ITALIAN syntax */
08871       return vm_intro_it(chan, vms);
08872    } else if (!strncasecmp(chan->language, "nl", 2)) {  /* DUTCH syntax */
08873       return vm_intro_nl(chan, vms);
08874    } else if (!strncasecmp(chan->language, "no", 2)) {  /* NORWEGIAN syntax */
08875       return vm_intro_no(chan, vms);
08876    } else if (!strncasecmp(chan->language, "pl", 2)) {  /* POLISH syntax */
08877       return vm_intro_pl(chan, vms);
08878    } else if (!strncasecmp(chan->language, "pt_BR", 5)) {  /* BRAZILIAN PORTUGUESE syntax */
08879       return vm_intro_pt_BR(chan, vms);
08880    } else if (!strncasecmp(chan->language, "pt", 2)) {  /* PORTUGUESE syntax */
08881       return vm_intro_pt(chan, vms);
08882    } else if (!strncasecmp(chan->language, "ru", 2)) {  /* RUSSIAN syntax */
08883       return vm_intro_multilang(chan, vms, "n");
08884    } else if (!strncasecmp(chan->language, "se", 2)) {  /* SWEDISH syntax */
08885       return vm_intro_se(chan, vms);
08886    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* UKRAINIAN syntax */
08887       return vm_intro_multilang(chan, vms, "n");
08888    } else if (!strncasecmp(chan->language, "vi", 2)) { /* VIETNAMESE syntax */
08889       return vm_intro_vi(chan, vms);
08890    } else if (!strncasecmp(chan->language, "zh", 2)) { /* CHINESE (Taiwan) syntax */
08891       return vm_intro_zh(chan, vms);
08892    } else {                                             /* Default to ENGLISH */
08893       return vm_intro_en(chan, vms);
08894    }
08895 }

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

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

08706 {
08707    int res;
08708    res = ast_play_and_wait(chan, "vm-youhave");
08709    if (!res) {
08710       if (vms->newmessages) {
08711          if (vms->newmessages == 1) {
08712             res = ast_play_and_wait(chan, "digits/jednu");
08713          } else {
08714             res = say_and_wait(chan, vms->newmessages, chan->language);
08715          }
08716          if (!res) {
08717             if ((vms->newmessages == 1))
08718                res = ast_play_and_wait(chan, "vm-novou");
08719             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08720                res = ast_play_and_wait(chan, "vm-nove");
08721             if (vms->newmessages > 4)
08722                res = ast_play_and_wait(chan, "vm-novych");
08723          }
08724          if (vms->oldmessages && !res)
08725             res = ast_play_and_wait(chan, "vm-and");
08726          else if (!res) {
08727             if ((vms->newmessages == 1))
08728                res = ast_play_and_wait(chan, "vm-zpravu");
08729             if ((vms->newmessages) > 1 && (vms->newmessages < 5))
08730                res = ast_play_and_wait(chan, "vm-zpravy");
08731             if (vms->newmessages > 4)
08732                res = ast_play_and_wait(chan, "vm-zprav");
08733          }
08734       }
08735       if (!res && vms->oldmessages) {
08736          res = say_and_wait(chan, vms->oldmessages, chan->language);
08737          if (!res) {
08738             if ((vms->oldmessages == 1))
08739                res = ast_play_and_wait(chan, "vm-starou");
08740             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08741                res = ast_play_and_wait(chan, "vm-stare");
08742             if (vms->oldmessages > 4)
08743                res = ast_play_and_wait(chan, "vm-starych");
08744          }
08745          if (!res) {
08746             if ((vms->oldmessages == 1))
08747                res = ast_play_and_wait(chan, "vm-zpravu");
08748             if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
08749                res = ast_play_and_wait(chan, "vm-zpravy");
08750             if (vms->oldmessages > 4)
08751                res = ast_play_and_wait(chan, "vm-zprav");
08752          }
08753       }
08754       if (!res) {
08755          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08756             res = ast_play_and_wait(chan, "vm-no");
08757             if (!res)
08758                res = ast_play_and_wait(chan, "vm-zpravy");
08759          }
08760       }
08761    }
08762    return res;
08763 }

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

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

08402 {
08403    /* Introduce messages they have */
08404    int res;
08405    res = ast_play_and_wait(chan, "vm-youhave");
08406    if (!res) {
08407       if (vms->newmessages) {
08408          if ((vms->newmessages == 1))
08409             res = ast_play_and_wait(chan, "digits/1F");
08410          else
08411             res = say_and_wait(chan, vms->newmessages, chan->language);
08412          if (!res)
08413             res = ast_play_and_wait(chan, "vm-INBOX");
08414          if (vms->oldmessages && !res)
08415             res = ast_play_and_wait(chan, "vm-and");
08416          else if (!res) {
08417             if ((vms->newmessages == 1))
08418                res = ast_play_and_wait(chan, "vm-message");
08419             else
08420                res = ast_play_and_wait(chan, "vm-messages");
08421          }
08422             
08423       }
08424       if (!res && vms->oldmessages) {
08425          if (vms->oldmessages == 1)
08426             res = ast_play_and_wait(chan, "digits/1F");
08427          else
08428             res = say_and_wait(chan, vms->oldmessages, chan->language);
08429          if (!res)
08430             res = ast_play_and_wait(chan, "vm-Old");
08431          if (!res) {
08432             if (vms->oldmessages == 1)
08433                res = ast_play_and_wait(chan, "vm-message");
08434             else
08435                res = ast_play_and_wait(chan, "vm-messages");
08436          }
08437       }
08438       if (!res) {
08439          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08440             res = ast_play_and_wait(chan, "vm-no");
08441             if (!res)
08442                res = ast_play_and_wait(chan, "vm-messages");
08443          }
08444       }
08445    }
08446    return res;
08447 }

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

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

08151 {
08152    int res;
08153 
08154    /* Introduce messages they have */
08155    res = ast_play_and_wait(chan, "vm-youhave");
08156    if (!res) {
08157       if (vms->urgentmessages) {
08158          res = say_and_wait(chan, vms->urgentmessages, chan->language);
08159          if (!res)
08160             res = ast_play_and_wait(chan, "vm-Urgent");
08161          if ((vms->oldmessages || vms->newmessages) && !res) {
08162             res = ast_play_and_wait(chan, "vm-and");
08163          } else if (!res) {
08164             if ((vms->urgentmessages == 1))
08165                res = ast_play_and_wait(chan, "vm-message");
08166             else
08167                res = ast_play_and_wait(chan, "vm-messages");
08168          }
08169       }
08170       if (vms->newmessages) {
08171          res = say_and_wait(chan, vms->newmessages, chan->language);
08172          if (!res)
08173             res = ast_play_and_wait(chan, "vm-INBOX");
08174          if (vms->oldmessages && !res)
08175             res = ast_play_and_wait(chan, "vm-and");
08176          else if (!res) {
08177             if ((vms->newmessages == 1))
08178                res = ast_play_and_wait(chan, "vm-message");
08179             else
08180                res = ast_play_and_wait(chan, "vm-messages");
08181          }
08182             
08183       }
08184       if (!res && vms->oldmessages) {
08185          res = say_and_wait(chan, vms->oldmessages, chan->language);
08186          if (!res)
08187             res = ast_play_and_wait(chan, "vm-Old");
08188          if (!res) {
08189             if (vms->oldmessages == 1)
08190                res = ast_play_and_wait(chan, "vm-message");
08191             else
08192                res = ast_play_and_wait(chan, "vm-messages");
08193          }
08194       }
08195       if (!res) {
08196          if (!vms->urgentmessages && !vms->oldmessages && !vms->newmessages) {
08197             res = ast_play_and_wait(chan, "vm-no");
08198             if (!res)
08199                res = ast_play_and_wait(chan, "vm-messages");
08200          }
08201       }
08202    }
08203    return res;
08204 }

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

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

08451 {
08452    /* Introduce messages they have */
08453    int res;
08454    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08455       res = ast_play_and_wait(chan, "vm-youhaveno");
08456       if (!res)
08457          res = ast_play_and_wait(chan, "vm-messages");
08458    } else {
08459       res = ast_play_and_wait(chan, "vm-youhave");
08460    }
08461    if (!res) {
08462       if (vms->newmessages) {
08463          if (!res) {
08464             if ((vms->newmessages == 1)) {
08465                res = ast_play_and_wait(chan, "digits/1M");
08466                if (!res)
08467                   res = ast_play_and_wait(chan, "vm-message");
08468                if (!res)
08469                   res = ast_play_and_wait(chan, "vm-INBOXs");
08470             } else {
08471                res = say_and_wait(chan, vms->newmessages, chan->language);
08472                if (!res)
08473                   res = ast_play_and_wait(chan, "vm-messages");
08474                if (!res)
08475                   res = ast_play_and_wait(chan, "vm-INBOX");
08476             }
08477          }
08478          if (vms->oldmessages && !res)
08479             res = ast_play_and_wait(chan, "vm-and");
08480       }
08481       if (vms->oldmessages) {
08482          if (!res) {
08483             if (vms->oldmessages == 1) {
08484                res = ast_play_and_wait(chan, "digits/1M");
08485                if (!res)
08486                   res = ast_play_and_wait(chan, "vm-message");
08487                if (!res)
08488                   res = ast_play_and_wait(chan, "vm-Olds");
08489             } else {
08490                res = say_and_wait(chan, vms->oldmessages, chan->language);
08491                if (!res)
08492                   res = ast_play_and_wait(chan, "vm-messages");
08493                if (!res)
08494                   res = ast_play_and_wait(chan, "vm-Old");
08495             }
08496          }
08497       }
08498    }
08499 return res;
08500 }

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

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

08549 {
08550    /* Introduce messages they have */
08551    int res;
08552    res = ast_play_and_wait(chan, "vm-youhave");
08553    if (!res) {
08554       if (vms->newmessages) {
08555          res = say_and_wait(chan, vms->newmessages, chan->language);
08556          if (!res)
08557             res = ast_play_and_wait(chan, "vm-INBOX");
08558          if (vms->oldmessages && !res)
08559             res = ast_play_and_wait(chan, "vm-and");
08560          else if (!res) {
08561             if ((vms->newmessages == 1))
08562                res = ast_play_and_wait(chan, "vm-message");
08563             else
08564                res = ast_play_and_wait(chan, "vm-messages");
08565          }
08566             
08567       }
08568       if (!res && vms->oldmessages) {
08569          res = say_and_wait(chan, vms->oldmessages, chan->language);
08570          if (!res)
08571             res = ast_play_and_wait(chan, "vm-Old");
08572          if (!res) {
08573             if (vms->oldmessages == 1)
08574                res = ast_play_and_wait(chan, "vm-message");
08575             else
08576                res = ast_play_and_wait(chan, "vm-messages");
08577          }
08578       }
08579       if (!res) {
08580          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08581             res = ast_play_and_wait(chan, "vm-no");
08582             if (!res)
08583                res = ast_play_and_wait(chan, "vm-messages");
08584          }
08585       }
08586    }
08587    return res;
08588 }

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

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

07950 {
07951    int res = 0;
07952 
07953    if (vms->newmessages) {
07954       res = ast_play_and_wait(chan, "vm-youhave");
07955       if (!res) 
07956          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
07957       if (!res) {
07958          if ((vms->newmessages == 1)) {
07959             res = ast_play_and_wait(chan, "vm-INBOX");
07960             if (!res)
07961                res = ast_play_and_wait(chan, "vm-message");
07962          } else {
07963             res = ast_play_and_wait(chan, "vm-INBOXs");
07964             if (!res)
07965                res = ast_play_and_wait(chan, "vm-messages");
07966          }
07967       }
07968    } else if (vms->oldmessages){
07969       res = ast_play_and_wait(chan, "vm-youhave");
07970       if (!res)
07971          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
07972       if ((vms->oldmessages == 1)){
07973          res = ast_play_and_wait(chan, "vm-Old");
07974          if (!res)
07975             res = ast_play_and_wait(chan, "vm-message");
07976       } else {
07977          res = ast_play_and_wait(chan, "vm-Olds");
07978          if (!res)
07979             res = ast_play_and_wait(chan, "vm-messages");
07980       }
07981    } else if (!vms->oldmessages && !vms->newmessages) 
07982       res = ast_play_and_wait(chan, "vm-denExeteMynhmata"); 
07983    return res;
07984 }

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

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

08084 {
08085    int res = 0;
08086 
08087    /* Introduce messages they have */
08088    if (!res) {
08089       if ((vms->newmessages) || (vms->oldmessages)) {
08090          res = ast_play_and_wait(chan, "vm-youhave");
08091       }
08092       /*
08093        * The word "shtei" refers to the number 2 in hebrew when performing a count
08094        * of elements. In Hebrew, there are 6 forms of enumerating the number 2 for
08095        * an element, this is one of them.
08096        */
08097       if (vms->newmessages) {
08098          if (!res) {
08099             if (vms->newmessages == 1) {
08100                res = ast_play_and_wait(chan, "vm-INBOX1");
08101             } else {
08102                if (vms->newmessages == 2) {
08103                   res = ast_play_and_wait(chan, "vm-shtei");
08104                } else {
08105                   res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08106                }
08107                res = ast_play_and_wait(chan, "vm-INBOX");
08108             }
08109          }
08110          if (vms->oldmessages && !res) {
08111             res = ast_play_and_wait(chan, "vm-and");
08112             if (vms->oldmessages == 1) {
08113                res = ast_play_and_wait(chan, "vm-Old1");
08114             } else {
08115                if (vms->oldmessages == 2) {
08116                   res = ast_play_and_wait(chan, "vm-shtei");
08117                } else {
08118                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08119                }
08120                res = ast_play_and_wait(chan, "vm-Old");
08121             }
08122          }
08123       }
08124       if (!res && vms->oldmessages && !vms->newmessages) {
08125          if (!res) {
08126             if (vms->oldmessages == 1) {
08127                res = ast_play_and_wait(chan, "vm-Old1");
08128             } else {
08129                if (vms->oldmessages == 2) {
08130                   res = ast_play_and_wait(chan, "vm-shtei");
08131                } else {
08132                   res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");            
08133                }
08134                res = ast_play_and_wait(chan, "vm-Old");
08135             }
08136          }
08137       }
08138       if (!res) {
08139          if (!vms->oldmessages && !vms->newmessages) {
08140             if (!res) {
08141                res = ast_play_and_wait(chan, "vm-nomessages");
08142             }
08143          }
08144       }
08145    }
08146    return res;
08147 }

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

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

08208 {
08209    /* Introduce messages they have */
08210    int res;
08211    if (!vms->oldmessages && !vms->newmessages &&!vms->urgentmessages)
08212       res = ast_play_and_wait(chan, "vm-no") ||
08213          ast_play_and_wait(chan, "vm-message");
08214    else
08215       res = ast_play_and_wait(chan, "vm-youhave");
08216    if (!res && vms->newmessages) {
08217       res = (vms->newmessages == 1) ?
08218          ast_play_and_wait(chan, "digits/un") ||
08219          ast_play_and_wait(chan, "vm-nuovo") ||
08220          ast_play_and_wait(chan, "vm-message") :
08221          /* 2 or more new messages */
08222          say_and_wait(chan, vms->newmessages, chan->language) ||
08223          ast_play_and_wait(chan, "vm-nuovi") ||
08224          ast_play_and_wait(chan, "vm-messages");
08225       if (!res && vms->oldmessages)
08226          res = ast_play_and_wait(chan, "vm-and");
08227    }
08228    if (!res && vms->oldmessages) {
08229       res = (vms->oldmessages == 1) ?
08230          ast_play_and_wait(chan, "digits/un") ||
08231          ast_play_and_wait(chan, "vm-vecchio") ||
08232          ast_play_and_wait(chan, "vm-message") :
08233          /* 2 or more old messages */
08234          say_and_wait(chan, vms->oldmessages, chan->language) ||
08235          ast_play_and_wait(chan, "vm-vecchi") ||
08236          ast_play_and_wait(chan, "vm-messages");
08237    }
08238    return res;
08239 }

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

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

08044 {
08045    int res;
08046    int lastnum = 0;
08047 
08048    res = ast_play_and_wait(chan, "vm-youhave");
08049 
08050    if (!res && vms->newmessages) {
08051       lastnum = vms->newmessages;
08052 
08053       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08054          res = ast_say_counted_adjective(chan, lastnum, "vm-new", message_gender);
08055       }
08056 
08057       if (!res && vms->oldmessages) {
08058          res = ast_play_and_wait(chan, "vm-and");
08059       }
08060    }
08061 
08062    if (!res && vms->oldmessages) {
08063       lastnum = vms->oldmessages;
08064 
08065       if (!(res = ast_say_number(chan, lastnum, AST_DIGIT_ANY, chan->language, message_gender))) {
08066          res = ast_say_counted_adjective(chan, lastnum, "vm-old", message_gender);
08067       }
08068    }
08069 
08070    if (!res) {
08071       if (lastnum == 0) {
08072          res = ast_play_and_wait(chan, "vm-no");
08073       }
08074       if (!res) {
08075          res = ast_say_counted_noun(chan, lastnum, "vm-message");
08076       }
08077    }
08078 
08079    return res;
08080 }

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

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

08592 {
08593    /* Introduce messages they have */
08594    int res;
08595    res = ast_play_and_wait(chan, "vm-youhave");
08596    if (!res) {
08597       if (vms->newmessages) {
08598          res = say_and_wait(chan, vms->newmessages, chan->language);
08599          if (!res) {
08600             if (vms->newmessages == 1)
08601                res = ast_play_and_wait(chan, "vm-INBOXs");
08602             else
08603                res = ast_play_and_wait(chan, "vm-INBOX");
08604          }
08605          if (vms->oldmessages && !res)
08606             res = ast_play_and_wait(chan, "vm-and");
08607          else if (!res) {
08608             if ((vms->newmessages == 1))
08609                res = ast_play_and_wait(chan, "vm-message");
08610             else
08611                res = ast_play_and_wait(chan, "vm-messages");
08612          }
08613             
08614       }
08615       if (!res && vms->oldmessages) {
08616          res = say_and_wait(chan, vms->oldmessages, chan->language);
08617          if (!res) {
08618             if (vms->oldmessages == 1)
08619                res = ast_play_and_wait(chan, "vm-Olds");
08620             else
08621                res = ast_play_and_wait(chan, "vm-Old");
08622          }
08623          if (!res) {
08624             if (vms->oldmessages == 1)
08625                res = ast_play_and_wait(chan, "vm-message");
08626             else
08627                res = ast_play_and_wait(chan, "vm-messages");
08628          }
08629       }
08630       if (!res) {
08631          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08632             res = ast_play_and_wait(chan, "vm-no");
08633             if (!res)
08634                res = ast_play_and_wait(chan, "vm-messages");
08635          }
08636       }
08637    }
08638    return res;
08639 }

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

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

08358 {
08359    /* Introduce messages they have */
08360    int res;
08361 
08362    res = ast_play_and_wait(chan, "vm-youhave");
08363    if (res)
08364       return res;
08365 
08366    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08367       res = ast_play_and_wait(chan, "vm-no");
08368       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08369       return res;
08370    }
08371 
08372    if (vms->newmessages) {
08373       if ((vms->newmessages == 1)) {
08374          res = ast_play_and_wait(chan, "digits/1");
08375          res = res ? res : ast_play_and_wait(chan, "vm-ny");
08376          res = res ? res : ast_play_and_wait(chan, "vm-message");
08377       } else {
08378          res = say_and_wait(chan, vms->newmessages, chan->language);
08379          res = res ? res : ast_play_and_wait(chan, "vm-nye");
08380          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08381       }
08382       if (!res && vms->oldmessages)
08383          res = ast_play_and_wait(chan, "vm-and");
08384    }
08385    if (!res && vms->oldmessages) {
08386       if (vms->oldmessages == 1) {
08387          res = ast_play_and_wait(chan, "digits/1");
08388          res = res ? res : ast_play_and_wait(chan, "vm-gamel");
08389          res = res ? res : ast_play_and_wait(chan, "vm-message");
08390       } else {
08391          res = say_and_wait(chan, vms->oldmessages, chan->language);
08392          res = res ? res : ast_play_and_wait(chan, "vm-gamle");
08393          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08394       }
08395    }
08396 
08397    return res;
08398 }

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

Definition at line 8242 of file app_voicemail_imapstorage.c.

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

08243 {
08244    /* Introduce messages they have */
08245    int res;
08246    div_t num;
08247 
08248    if (!vms->oldmessages && !vms->newmessages) {
08249       res = ast_play_and_wait(chan, "vm-no");
08250       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08251       return res;
08252    } else {
08253       res = ast_play_and_wait(chan, "vm-youhave");
08254    }
08255 
08256    if (vms->newmessages) {
08257       num = div(vms->newmessages, 10);
08258       if (vms->newmessages == 1) {
08259          res = ast_play_and_wait(chan, "digits/1-a");
08260          res = res ? res : ast_play_and_wait(chan, "vm-new-a");
08261          res = res ? res : ast_play_and_wait(chan, "vm-message");
08262       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08263          if (num.rem == 2) {
08264             if (!num.quot) {
08265                res = ast_play_and_wait(chan, "digits/2-ie");
08266             } else {
08267                res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
08268                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08269             }
08270          } else {
08271             res = say_and_wait(chan, vms->newmessages, chan->language);
08272          }
08273          res = res ? res : ast_play_and_wait(chan, "vm-new-e");
08274          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08275       } else {
08276          res = say_and_wait(chan, vms->newmessages, chan->language);
08277          res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
08278          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08279       }
08280       if (!res && vms->oldmessages)
08281          res = ast_play_and_wait(chan, "vm-and");
08282    }
08283    if (!res && vms->oldmessages) {
08284       num = div(vms->oldmessages, 10);
08285       if (vms->oldmessages == 1) {
08286          res = ast_play_and_wait(chan, "digits/1-a");
08287          res = res ? res : ast_play_and_wait(chan, "vm-old-a");
08288          res = res ? res : ast_play_and_wait(chan, "vm-message");
08289       } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
08290          if (num.rem == 2) {
08291             if (!num.quot) {
08292                res = ast_play_and_wait(chan, "digits/2-ie");
08293             } else {
08294                res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
08295                res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
08296             }
08297          } else {
08298             res = say_and_wait(chan, vms->oldmessages, chan->language);
08299          }
08300          res = res ? res : ast_play_and_wait(chan, "vm-old-e");
08301          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08302       } else {
08303          res = say_and_wait(chan, vms->oldmessages, chan->language);
08304          res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
08305          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08306       }
08307    }
08308 
08309    return res;
08310 }

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

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

08643 {
08644    /* Introduce messages they have */
08645    int res;
08646    res = ast_play_and_wait(chan, "vm-youhave");
08647    if (!res) {
08648       if (vms->newmessages) {
08649          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08650          if (!res) {
08651             if ((vms->newmessages == 1)) {
08652                res = ast_play_and_wait(chan, "vm-message");
08653                if (!res)
08654                   res = ast_play_and_wait(chan, "vm-INBOXs");
08655             } else {
08656                res = ast_play_and_wait(chan, "vm-messages");
08657                if (!res)
08658                   res = ast_play_and_wait(chan, "vm-INBOX");
08659             }
08660          }
08661          if (vms->oldmessages && !res)
08662             res = ast_play_and_wait(chan, "vm-and");
08663       }
08664       if (!res && vms->oldmessages) {
08665          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08666          if (!res) {
08667             if (vms->oldmessages == 1) {
08668                res = ast_play_and_wait(chan, "vm-message");
08669                if (!res)
08670                   res = ast_play_and_wait(chan, "vm-Olds");
08671             } else {
08672                res = ast_play_and_wait(chan, "vm-messages");
08673                if (!res)
08674                   res = ast_play_and_wait(chan, "vm-Old");
08675             }
08676          }
08677       }
08678       if (!res) {
08679          if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08680             res = ast_play_and_wait(chan, "vm-no");
08681             if (!res)
08682                res = ast_play_and_wait(chan, "vm-messages");
08683          }
08684       }
08685    }
08686    return res;
08687 }

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

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

08503                                                                           {
08504    /* Introduce messages they have */
08505    int res;
08506    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08507       res = ast_play_and_wait(chan, "vm-nomessages");
08508       return res;
08509    } else {
08510       res = ast_play_and_wait(chan, "vm-youhave");
08511    }
08512    if (vms->newmessages) {
08513       if (!res)
08514          res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
08515       if ((vms->newmessages == 1)) {
08516          if (!res)
08517             res = ast_play_and_wait(chan, "vm-message");
08518          if (!res)
08519             res = ast_play_and_wait(chan, "vm-INBOXs");
08520       } else {
08521          if (!res)
08522             res = ast_play_and_wait(chan, "vm-messages");
08523          if (!res)
08524             res = ast_play_and_wait(chan, "vm-INBOX");
08525       }
08526       if (vms->oldmessages && !res)
08527          res = ast_play_and_wait(chan, "vm-and");
08528    }
08529    if (vms->oldmessages) {
08530       if (!res)
08531          res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
08532       if (vms->oldmessages == 1) {
08533          if (!res)
08534             res = ast_play_and_wait(chan, "vm-message");
08535          if (!res)
08536             res = ast_play_and_wait(chan, "vm-Olds");
08537       } else {
08538          if (!res)
08539             res = ast_play_and_wait(chan, "vm-messages");
08540          if (!res)
08541             res = ast_play_and_wait(chan, "vm-Old");
08542       }
08543    }
08544    return res;
08545 }

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

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

08314 {
08315    /* Introduce messages they have */
08316    int res;
08317 
08318    res = ast_play_and_wait(chan, "vm-youhave");
08319    if (res)
08320       return res;
08321 
08322    if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
08323       res = ast_play_and_wait(chan, "vm-no");
08324       res = res ? res : ast_play_and_wait(chan, "vm-messages");
08325       return res;
08326    }
08327 
08328    if (vms->newmessages) {
08329       if ((vms->newmessages == 1)) {
08330          res = ast_play_and_wait(chan, "digits/ett");
08331          res = res ? res : ast_play_and_wait(chan, "vm-nytt");
08332          res = res ? res : ast_play_and_wait(chan, "vm-message");
08333       } else {
08334          res = say_and_wait(chan, vms->newmessages, chan->language);
08335          res = res ? res : ast_play_and_wait(chan, "vm-nya");
08336          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08337       }
08338       if (!res && vms->oldmessages)
08339          res = ast_play_and_wait(chan, "vm-and");
08340    }
08341    if (!res && vms->oldmessages) {
08342       if (vms->oldmessages == 1) {
08343          res = ast_play_and_wait(chan, "digits/ett");
08344          res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
08345          res = res ? res : ast_play_and_wait(chan, "vm-message");
08346       } else {
08347          res = say_and_wait(chan, vms->oldmessages, chan->language);
08348          res = res ? res : ast_play_and_wait(chan, "vm-gamla");
08349          res = res ? res : ast_play_and_wait(chan, "vm-messages");
08350       }
08351    }
08352 
08353    return res;
08354 }

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

Definition at line 8805 of file app_voicemail_imapstorage.c.

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

08806 {
08807    int res;
08808 
08809    /* Introduce messages they have */
08810    res = ast_play_and_wait(chan, "vm-youhave");
08811    if (!res) {
08812       if (vms->newmessages) {
08813          res = say_and_wait(chan, vms->newmessages, chan->language);
08814          if (!res)
08815             res = ast_play_and_wait(chan, "vm-INBOX");
08816          if (vms->oldmessages && !res)
08817             res = ast_play_and_wait(chan, "vm-and");
08818       }
08819       if (!res && vms->oldmessages) {
08820          res = say_and_wait(chan, vms->oldmessages, chan->language);
08821          if (!res)
08822             res = ast_play_and_wait(chan, "vm-Old");        
08823       }
08824       if (!res) {
08825          if (!vms->oldmessages && !vms->newmessages) {
08826             res = ast_play_and_wait(chan, "vm-no");
08827             if (!res)
08828                res = ast_play_and_wait(chan, "vm-message");
08829          }
08830       }
08831    }
08832    return res;
08833 }

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

Definition at line 8766 of file app_voicemail_imapstorage.c.

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

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

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

References ast_lock_path(), and AST_LOCK_TIMEOUT.

03181 {
03182    switch (ast_lock_path(path)) {
03183    case AST_LOCK_TIMEOUT:
03184       return -1;
03185    default:
03186       return 0;
03187    }
03188 }

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

Definition at line 1586 of file app_voicemail_imapstorage.c.

References VOICEMAIL_FILE_MODE.

01587 {
01588    FILE *p = NULL;
01589    int pfd = mkstemp(template);
01590    chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01591    if (pfd > -1) {
01592       p = fdopen(pfd, "w+");
01593       if (!p) {
01594          close(pfd);
01595          pfd = -1;
01596       }
01597    }
01598    return p;
01599 }

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 9008 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, check_password(), play_record_review(), 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, and vm_reenterpassword.

09009 {
09010    int cmd = 0;
09011    int duration = 0;
09012    int tries = 0;
09013    char newpassword[80] = "";
09014    char newpassword2[80] = "";
09015    char prefile[PATH_MAX] = "";
09016    unsigned char buf[256];
09017    int bytes = 0;
09018 
09019    if (ast_adsi_available(chan)) {
09020       bytes += adsi_logo(buf + bytes);
09021       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
09022       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09023       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09024       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09025       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09026    }
09027 
09028    /* First, have the user change their password 
09029       so they won't get here again */
09030    for (;;) {
09031       newpassword[1] = '\0';
09032       newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09033       if (cmd == '#')
09034          newpassword[0] = '\0';
09035       if (cmd < 0 || cmd == 't' || cmd == '#')
09036          return cmd;
09037       cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#");
09038       if (cmd < 0 || cmd == 't' || cmd == '#')
09039          return cmd;
09040       cmd = check_password(vmu, newpassword); /* perform password validation */
09041       if (cmd != 0) {
09042          ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09043          cmd = ast_play_and_wait(chan, vm_invalid_password);
09044       } else {
09045          newpassword2[1] = '\0';
09046          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09047          if (cmd == '#')
09048             newpassword2[0] = '\0';
09049          if (cmd < 0 || cmd == 't' || cmd == '#')
09050             return cmd;
09051          cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#");
09052          if (cmd < 0 || cmd == 't' || cmd == '#')
09053             return cmd;
09054          if (!strcmp(newpassword, newpassword2))
09055             break;
09056          ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09057          cmd = ast_play_and_wait(chan, vm_mismatch);
09058       }
09059       if (++tries == 3)
09060          return -1;
09061       if (cmd != 0) {
09062          cmd = ast_play_and_wait(chan, vm_pls_try_again);
09063       }
09064    }
09065    if (pwdchange & PWDCHANGE_INTERNAL)
09066       vm_change_password(vmu, newpassword);
09067    if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09068       vm_change_password_shell(vmu, newpassword);
09069 
09070    ast_debug(1, "User %s set password to %s of length %d\n", vms->username, newpassword, (int) strlen(newpassword));
09071    cmd = ast_play_and_wait(chan, vm_passchanged);
09072 
09073    /* If forcename is set, have the user record their name */  
09074    if (ast_test_flag(vmu, VM_FORCENAME)) {
09075       snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09076       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09077          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09078          if (cmd < 0 || cmd == 't' || cmd == '#')
09079             return cmd;
09080       }
09081    }
09082 
09083    /* If forcegreetings is set, have the user record their greetings */
09084    if (ast_test_flag(vmu, VM_FORCEGREET)) {
09085       snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09086       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09087          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09088          if (cmd < 0 || cmd == 't' || cmd == '#')
09089             return cmd;
09090       }
09091 
09092       snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09093       if (ast_fileexists(prefile, NULL, NULL) < 1) {
09094          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09095          if (cmd < 0 || cmd == 't' || cmd == '#')
09096             return cmd;
09097       }
09098    }
09099 
09100    return cmd;
09101 }

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 9103 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_waitfordigit(), check_password(), ast_vm_user::context, DISPOSE, ast_vm_user::password, play_record_review(), 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, and vm_tempgreeting().

09104 {
09105    int cmd = 0;
09106    int retries = 0;
09107    int duration = 0;
09108    char newpassword[80] = "";
09109    char newpassword2[80] = "";
09110    char prefile[PATH_MAX] = "";
09111    unsigned char buf[256];
09112    int bytes = 0;
09113 
09114    if (ast_adsi_available(chan)) {
09115       bytes += adsi_logo(buf + bytes);
09116       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
09117       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09118       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09119       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09120       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09121    }
09122    while ((cmd >= 0) && (cmd != 't')) {
09123       if (cmd)
09124          retries = 0;
09125       switch (cmd) {
09126       case '1': /* Record your unavailable message */
09127          snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
09128          cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09129          break;
09130       case '2':  /* Record your busy message */
09131          snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
09132          cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09133          break;
09134       case '3': /* Record greeting */
09135          snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
09136          cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09137          break;
09138       case '4':  /* manage the temporary greeting */
09139          cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
09140          break;
09141       case '5': /* change password */
09142          if (vmu->password[0] == '-') {
09143             cmd = ast_play_and_wait(chan, "vm-no");
09144             break;
09145          }
09146          newpassword[1] = '\0';
09147          newpassword[0] = cmd = ast_play_and_wait(chan, vm_newpassword);
09148          if (cmd == '#')
09149             newpassword[0] = '\0';
09150          else {
09151             if (cmd < 0)
09152                break;
09153             if ((cmd = ast_readstring(chan, newpassword + strlen(newpassword), sizeof(newpassword) - 1, 2000, 10000, "#")) < 0) {
09154                break;
09155             }
09156          }
09157          cmd = check_password(vmu, newpassword); /* perform password validation */
09158          if (cmd != 0) {
09159             ast_log(AST_LOG_NOTICE, "Invalid password for user %s (%s)\n", vms->username, newpassword);
09160             cmd = ast_play_and_wait(chan, vm_invalid_password);
09161             if (!cmd) {
09162                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09163             }
09164             break;
09165          }
09166          newpassword2[1] = '\0';
09167          newpassword2[0] = cmd = ast_play_and_wait(chan, vm_reenterpassword);
09168          if (cmd == '#')
09169             newpassword2[0] = '\0';
09170          else {
09171             if (cmd < 0)
09172                break;
09173 
09174             if ((cmd = ast_readstring(chan, newpassword2 + strlen(newpassword2), sizeof(newpassword2) - 1, 2000, 10000, "#")) < 0) {
09175                break;
09176             }
09177          }
09178          if (strcmp(newpassword, newpassword2)) {
09179             ast_log(AST_LOG_NOTICE, "Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
09180             cmd = ast_play_and_wait(chan, vm_mismatch);
09181             if (!cmd) {
09182                cmd = ast_play_and_wait(chan, vm_pls_try_again);
09183             }
09184             break;
09185          }
09186          if (pwdchange & PWDCHANGE_INTERNAL)
09187             vm_change_password(vmu, newpassword);
09188          if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd))
09189             vm_change_password_shell(vmu, newpassword);
09190 
09191          ast_debug(1, "User %s set password to %s of length %d\n",
09192             vms->username, newpassword, (int) strlen(newpassword));
09193          cmd = ast_play_and_wait(chan, vm_passchanged);
09194          break;
09195       case '*': 
09196          cmd = 't';
09197          break;
09198       default: 
09199          cmd = 0;
09200          snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09201          RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09202          if (ast_fileexists(prefile, NULL, NULL)) {
09203             cmd = ast_play_and_wait(chan, "vm-tmpexists");
09204          }
09205          DISPOSE(prefile, -1);
09206          if (!cmd) {
09207             cmd = ast_play_and_wait(chan, "vm-options");
09208          }
09209          if (!cmd) {
09210             cmd = ast_waitfordigit(chan, 6000);
09211          }
09212          if (!cmd) {
09213             retries++;
09214          }
09215          if (retries > 3) {
09216             cmd = 't';
09217          }
09218       }
09219    }
09220    if (cmd == 't')
09221       cmd = 0;
09222    return cmd;
09223 }

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

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

07913 {
07914    int cmd;
07915 
07916    if (  !strncasecmp(chan->language, "it", 2) ||
07917         !strncasecmp(chan->language, "es", 2) ||
07918         !strncasecmp(chan->language, "pt", 2)) { /* Italian, Spanish, or Portuguese syntax */
07919       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */
07920       return cmd ? cmd : ast_play_and_wait(chan, box);
07921    } else if (!strncasecmp(chan->language, "gr", 2)) {
07922       return vm_play_folder_name_gr(chan, box);
07923    } else if (!strncasecmp(chan->language, "he", 2)) {  /* Hebrew syntax */
07924       return ast_play_and_wait(chan, box);
07925    } else if (!strncasecmp(chan->language, "pl", 2)) {
07926       return vm_play_folder_name_pl(chan, box);
07927    } else if (!strncasecmp(chan->language, "ua", 2)) {  /* Ukrainian syntax */
07928       return vm_play_folder_name_ua(chan, box);
07929    } else if (!strncasecmp(chan->language, "vi", 2)) {
07930       return ast_play_and_wait(chan, box);
07931    } else {  /* Default English */
07932       cmd = ast_play_and_wait(chan, box);
07933       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages */
07934    }
07935 }

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

Definition at line 7865 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

07866 {
07867    int cmd;
07868    char *buf;
07869 
07870    buf = alloca(strlen(box) + 2);
07871    strcpy(buf, box);
07872    strcat(buf, "s");
07873 
07874    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")){
07875       cmd = ast_play_and_wait(chan, buf); /* "NEA / PALIA" */
07876       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07877    } else {
07878       cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages" -> "MYNHMATA" */
07879       return cmd ? cmd : ast_play_and_wait(chan, box); /* friends/family/work... -> "FILWN"/"OIKOGENIAS"/"DOULEIAS"*/
07880    }
07881 }

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

Definition at line 7883 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

07884 {
07885    int cmd;
07886 
07887    if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
07888       if (!strcasecmp(box, "vm-INBOX"))
07889          cmd = ast_play_and_wait(chan, "vm-new-e");
07890       else
07891          cmd = ast_play_and_wait(chan, "vm-old-e");
07892       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07893    } else {
07894       cmd = ast_play_and_wait(chan, "vm-messages");
07895       return cmd ? cmd : ast_play_and_wait(chan, box);
07896    }
07897 }

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

Definition at line 7899 of file app_voicemail_imapstorage.c.

References ast_play_and_wait().

07900 {
07901    int cmd;
07902 
07903    if (!strcasecmp(box, "vm-Family") || !strcasecmp(box, "vm-Friends") || !strcasecmp(box, "vm-Work")){
07904       cmd = ast_play_and_wait(chan, "vm-messages");
07905       return cmd ? cmd : ast_play_and_wait(chan, box);
07906    } else {
07907       cmd = ast_play_and_wait(chan, box);
07908       return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
07909    }
07910 }

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 9241 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_waitfordigit(), ast_vm_user::context, DELETE, DISPOSE, ast_vm_user::mailbox, play_record_review(), RETRIEVE, and vm_state::username.

09242 {
09243    int cmd = 0;
09244    int retries = 0;
09245    int duration = 0;
09246    char prefile[PATH_MAX] = "";
09247    unsigned char buf[256];
09248    int bytes = 0;
09249 
09250    if (ast_adsi_available(chan)) {
09251       bytes += adsi_logo(buf + bytes);
09252       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
09253       bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
09254       bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
09255       bytes += ast_adsi_voice_mode(buf + bytes, 0);
09256       ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
09257    }
09258 
09259    snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
09260    while ((cmd >= 0) && (cmd != 't')) {
09261       if (cmd)
09262          retries = 0;
09263       RETRIEVE(prefile, -1, vmu->mailbox, vmu->context);
09264       if (ast_fileexists(prefile, NULL, NULL) <= 0) {
09265          play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09266          cmd = 't';  
09267       } else {
09268          switch (cmd) {
09269          case '1':
09270             cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms, NULL);
09271             break;
09272          case '2':
09273             DELETE(prefile, -1, prefile, vmu);
09274             ast_play_and_wait(chan, "vm-tempremoved");
09275             cmd = 't';  
09276             break;
09277          case '*': 
09278             cmd = 't';
09279             break;
09280          default:
09281             cmd = ast_play_and_wait(chan,
09282                ast_fileexists(prefile, NULL, NULL) > 0 ? /* XXX always true ? */
09283                   "vm-tempgreeting2" : "vm-tempgreeting");
09284             if (!cmd)
09285                cmd = ast_waitfordigit(chan, 6000);
09286             if (!cmd)
09287                retries++;
09288             if (retries > 3)
09289                cmd = 't';
09290          }
09291       }
09292       DISPOSE(prefile, -1);
09293    }
09294    if (cmd == 't')
09295       cmd = 0;
09296    return cmd;
09297 }

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

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

11131 {
11132    struct ast_vm_user *user;
11133 
11134    AST_LIST_LOCK(&users);
11135    AST_LIST_TRAVERSE(&users, user, list) {
11136       vm_users_data_provider_get_helper(search, data_root, user);
11137    }
11138    AST_LIST_UNLOCK(&users);
11139 
11140    return 0;
11141 }

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

11084 {
11085    struct ast_data *data_user, *data_zone;
11086    struct ast_data *data_state;
11087    struct vm_zone *zone = NULL;
11088    int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11089    char ext_context[256] = "";
11090 
11091    data_user = ast_data_add_node(data_root, "user");
11092    if (!data_user) {
11093       return -1;
11094    }
11095 
11096    ast_data_add_structure(ast_vm_user, data_user, user);
11097 
11098    AST_LIST_LOCK(&zones);
11099    AST_LIST_TRAVERSE(&zones, zone, list) {
11100       if (!strcmp(zone->name, user->zonetag)) {
11101          break;
11102       }
11103    }
11104    AST_LIST_UNLOCK(&zones);
11105 
11106    /* state */
11107    data_state = ast_data_add_node(data_user, "state");
11108    if (!data_state) {
11109       return -1;
11110    }
11111    snprintf(ext_context, sizeof(ext_context), "%s@%s", user->mailbox, user->context);
11112    inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11113    ast_data_add_int(data_state, "urgentmsg", urgentmsg);
11114    ast_data_add_int(data_state, "newmsg", newmsg);
11115    ast_data_add_int(data_state, "oldmsg", oldmsg);
11116 
11117    if (zone) {
11118       data_zone = ast_data_add_node(data_user, "zone");
11119       ast_data_add_structure(vm_zone, data_zone, zone);
11120    }
11121 
11122    if (!ast_data_search_match(search, data_user)) {
11123       ast_data_remove_node(data_root, data_user);
11124    }
11125 
11126    return 0;
11127 }

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

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

10769 {
10770    char *s, *user = NULL, *context = NULL, mailbox[AST_MAX_EXTENSION] = "";
10771    struct ast_vm_user vmus;
10772    char *options = NULL;
10773    int silent = 0, skipuser = 0;
10774    int res = -1;
10775    
10776    if (data) {
10777       s = ast_strdupa(data);
10778       user = strsep(&s, ",");
10779       options = strsep(&s, ",");
10780       if (user) {
10781          s = user;
10782          user = strsep(&s, "@");
10783          context = strsep(&s, "");
10784          if (!ast_strlen_zero(user))
10785             skipuser++;
10786          ast_copy_string(mailbox, user, sizeof(mailbox));
10787       }
10788    }
10789 
10790    if (options) {
10791       silent = (strchr(options, 's')) != NULL;
10792    }
10793 
10794    if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
10795       pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
10796       pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
10797       ast_play_and_wait(chan, "auth-thankyou");
10798       res = 0;
10799    } else if (mailbox[0] == '*') {
10800       /* user entered '*' */
10801       if (!ast_goto_if_exists(chan, chan->context, "a", 1)) {
10802          res = 0; /* prevent hangup */
10803       }
10804    }
10805 
10806    return res;
10807 }

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

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

12256 {
12257    char *context;
12258    char *args_copy;
12259    int res;
12260 
12261    if (ast_strlen_zero(data)) {
12262       ast_log(LOG_WARNING, "VMSayName requires argument mailbox@context");
12263       return -1;
12264    }
12265 
12266    args_copy = ast_strdupa(data);
12267    if ((context = strchr(args_copy, '@'))) {
12268       *context++ = '\0';
12269    } else {
12270       context = "default";
12271    }
12272 
12273    if ((res = sayname(chan, args_copy, context) < 0)) {
12274       ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12275       res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
12276       if (!res) {
12277          res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, chan->language);
12278       }
12279    }
12280 
12281    return res;
12282 }

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

04289 {
04290    const struct vm_zone *z = NULL;
04291    struct timeval t = ast_tvnow();
04292 
04293    /* Does this user have a timezone specified? */
04294    if (!ast_strlen_zero(vmu->zonetag)) {
04295       /* Find the zone in the list */
04296       AST_LIST_LOCK(&zones);
04297       AST_LIST_TRAVERSE(&zones, z, list) {
04298          if (!strcmp(z->name, vmu->zonetag))
04299             break;
04300       }
04301       AST_LIST_UNLOCK(&zones);
04302    }
04303    ast_localtime(&t, tm, z ? z->timezone : NULL);
04304    return tm;
04305 }

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

Definition at line 7288 of file app_voicemail_imapstorage.c.

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

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

Definition at line 7280 of file app_voicemail_imapstorage.c.

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

07281 {
07282    int res;
07283    if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0) 
07284       ast_log(AST_LOG_WARNING, "Unable to play message %s\n", file); 
07285    return res;
07286 }

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

Definition at line 12229 of file app_voicemail_imapstorage.c.

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

12229                                                                               {
12230    struct ast_config *conf;
12231    struct ast_category *cat;
12232    struct ast_variable *var;
12233 
12234    if (!(conf=ast_config_new())) {
12235       ast_log(LOG_ERROR, "Error creating new config structure\n");
12236       return -1;
12237    }
12238    if (!(cat=ast_category_new("general","",1))) {
12239       ast_log(LOG_ERROR, "Error creating new category structure\n");
12240       return -1;
12241    }
12242    if (!(var=ast_variable_new("password",password,""))) {
12243       ast_log(LOG_ERROR, "Error creating new variable structure\n");
12244       return -1;
12245    }
12246    ast_category_append(conf,cat);
12247    ast_variable_append(cat,var);
12248    if (ast_config_text_file_save(secretfn, conf, "app_voicemail")) {
12249       ast_log(LOG_ERROR, "Error writing voicemail password to %s\n", secretfn);
12250       return -1;
12251    }
12252    return 0;
12253 }


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

Definition at line 13243 of file app_voicemail_imapstorage.c.

char* addesc = "Comedian Mail" [static]

Definition at line 739 of file app_voicemail_imapstorage.c.

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

Definition at line 854 of file app_voicemail_imapstorage.c.

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

Definition at line 855 of file app_voicemail_imapstorage.c.

int adsiver = 1 [static]

Definition at line 856 of file app_voicemail_imapstorage.c.

char* app = "VoiceMail" [static]

Definition at line 742 of file app_voicemail_imapstorage.c.

char* app2 = "VoiceMailMain" [static]

Definition at line 745 of file app_voicemail_imapstorage.c.

char* app3 = "MailboxExists" [static]

Definition at line 747 of file app_voicemail_imapstorage.c.

char* app4 = "VMAuthenticate" [static]

Definition at line 748 of file app_voicemail_imapstorage.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 13243 of file app_voicemail_imapstorage.c.

char callcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 840 of file app_voicemail_imapstorage.c.

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

Definition at line 852 of file app_voicemail_imapstorage.c.

char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64] [static]

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

char dialcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 839 of file app_voicemail_imapstorage.c.

char* emailbody = NULL [static]

Definition at line 846 of file app_voicemail_imapstorage.c.

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

Definition at line 857 of file app_voicemail_imapstorage.c.

char* emailsubject = NULL [static]

Definition at line 847 of file app_voicemail_imapstorage.c.

char exitcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 841 of file app_voicemail_imapstorage.c.

char ext_pass_check_cmd[128] [static]

Definition at line 719 of file app_voicemail_imapstorage.c.

char ext_pass_cmd[128] [static]

Definition at line 718 of file app_voicemail_imapstorage.c.

char externnotify[160] [static]

Definition at line 762 of file app_voicemail_imapstorage.c.

char fromstring[100] [static]

Definition at line 850 of file app_voicemail_imapstorage.c.

struct ast_flags globalflags = {0} [static]

Definition at line 835 of file app_voicemail_imapstorage.c.

struct ao2_container* inprocess_container

Definition at line 877 of file app_voicemail_imapstorage.c.

char listen_control_forward_key[12] [static]

Definition at line 820 of file app_voicemail_imapstorage.c.

char listen_control_pause_key[12] [static]

Definition at line 822 of file app_voicemail_imapstorage.c.

char listen_control_restart_key[12] [static]

Definition at line 823 of file app_voicemail_imapstorage.c.

char listen_control_reverse_key[12] [static]

Definition at line 821 of file app_voicemail_imapstorage.c.

char listen_control_stop_key[12] [static]

Definition at line 824 of file app_voicemail_imapstorage.c.

char locale[20] [static]

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

const char* const mailbox_folders[] [static]

Definition at line 1622 of file app_voicemail_imapstorage.c.

char mailcmd[160] [static]

Definition at line 761 of file app_voicemail_imapstorage.c.

int maxdeletedmsg [static]

Definition at line 758 of file app_voicemail_imapstorage.c.

int maxgreet [static]

Definition at line 768 of file app_voicemail_imapstorage.c.

int maxlogins [static]

Definition at line 770 of file app_voicemail_imapstorage.c.

int maxmsg [static]

Definition at line 757 of file app_voicemail_imapstorage.c.

int maxsilence [static]

Definition at line 756 of file app_voicemail_imapstorage.c.

int minpassword [static]

Definition at line 771 of file app_voicemail_imapstorage.c.

struct ast_event_sub* mwi_sub_sub [static]

Subscription to ... MWI event subscriptions

Definition at line 789 of file app_voicemail_imapstorage.c.

struct ast_taskprocessor* mwi_subscription_tps [static]

Definition at line 815 of file app_voicemail_imapstorage.c.

struct ast_event_sub* mwi_unsub_sub [static]

Subscription to ... MWI event un-subscriptions

Definition at line 791 of file app_voicemail_imapstorage.c.

int my_umask [static]

Definition at line 721 of file app_voicemail_imapstorage.c.

char* pagerbody = NULL [static]

Definition at line 848 of file app_voicemail_imapstorage.c.

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

Definition at line 858 of file app_voicemail_imapstorage.c.

char pagerfromstring[100] [static]

Definition at line 851 of file app_voicemail_imapstorage.c.

char* pagersubject = NULL [static]

Definition at line 849 of file app_voicemail_imapstorage.c.

int passwordlocation [static]

Definition at line 772 of file app_voicemail_imapstorage.c.

ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 784 of file app_voicemail_imapstorage.c.

unsigned int poll_freq [static]

Polling frequency

Definition at line 779 of file app_voicemail_imapstorage.c.

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

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

pthread_t poll_thread = AST_PTHREADT_NULL [static]

Definition at line 785 of file app_voicemail_imapstorage.c.

unsigned char poll_thread_run [static]

Definition at line 786 of file app_voicemail_imapstorage.c.

int pwdchange = PWDCHANGE_INTERNAL [static]

Definition at line 725 of file app_voicemail_imapstorage.c.

int saydurationminfo [static]

Definition at line 837 of file app_voicemail_imapstorage.c.

char* sayname_app = "VMSayName" [static]

Definition at line 750 of file app_voicemail_imapstorage.c.

char serveremail[80] [static]

Definition at line 760 of file app_voicemail_imapstorage.c.

int silencethreshold = 128 [static]

Definition at line 759 of file app_voicemail_imapstorage.c.

int skipms [static]

Definition at line 769 of file app_voicemail_imapstorage.c.

struct ast_smdi_interface* smdi_iface = NULL [static]

Definition at line 763 of file app_voicemail_imapstorage.c.

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

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

struct ast_data_entry vm_data_providers[] [static]

Initial value:

 {

}

Definition at line 11148 of file app_voicemail_imapstorage.c.

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

Definition at line 832 of file app_voicemail_imapstorage.c.

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

Definition at line 831 of file app_voicemail_imapstorage.c.

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

Definition at line 828 of file app_voicemail_imapstorage.c.

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

Definition at line 829 of file app_voicemail_imapstorage.c.

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

Definition at line 827 of file app_voicemail_imapstorage.c.

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

Definition at line 833 of file app_voicemail_imapstorage.c.

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

Definition at line 830 of file app_voicemail_imapstorage.c.

char VM_SPOOL_DIR[PATH_MAX] [static]

Definition at line 716 of file app_voicemail_imapstorage.c.

struct ast_data_handler vm_users_data_provider [static]

Initial value:

Definition at line 11143 of file app_voicemail_imapstorage.c.

char vmfmts[80] [static]

Definition at line 764 of file app_voicemail_imapstorage.c.

int vmmaxsecs [static]

Definition at line 767 of file app_voicemail_imapstorage.c.

int vmminsecs [static]

Definition at line 766 of file app_voicemail_imapstorage.c.

double volgain [static]

Definition at line 765 of file app_voicemail_imapstorage.c.

char zonetag[80] [static]

Definition at line 754 of file app_voicemail_imapstorage.c.


Generated on Mon Jun 27 16:51:01 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7