1999-11-21 21:15:14 +00:00
/*
* Asterisk - - A telephony toolkit for Linux .
*
* Voicemail System ( did you ever think it could be so easy ? )
*
2003-11-13 01:47:23 +00:00
* Copyright ( C ) 2003 , Digium Inc .
1999-11-21 21:15:14 +00:00
*
2003-11-13 01:47:23 +00:00
* Mark Spencer < markster @ digium . com >
1999-11-21 21:15:14 +00:00
*
* This program is free software , distributed under the terms of
* the GNU General Public License
*/
2002-06-28 15:21:23 +00:00
# include <asterisk/lock.h>
1999-11-21 21:15:14 +00:00
# include <asterisk/file.h>
# include <asterisk/logger.h>
# include <asterisk/channel.h>
2003-11-13 01:47:23 +00:00
# include <asterisk/channel_pvt.h>
1999-11-21 21:15:14 +00:00
# include <asterisk/pbx.h>
# include <asterisk/options.h>
# include <asterisk/config.h>
# include <asterisk/say.h>
# include <asterisk/module.h>
2001-12-27 11:07:33 +00:00
# include <asterisk/adsi.h>
2003-01-30 15:03:20 +00:00
# include <asterisk/app.h>
2003-02-24 06:00:18 +00:00
# include <asterisk/manager.h>
2003-05-03 16:09:56 +00:00
# include <asterisk/dsp.h>
2003-11-13 01:47:23 +00:00
# include <asterisk/localtime.h>
1999-11-21 21:15:14 +00:00
# include <stdlib.h>
# include <errno.h>
# include <unistd.h>
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# include <sys/time.h>
# include <sys/stat.h>
# include <time.h>
2003-11-13 01:47:23 +00:00
/* we define USESQLVM when we have MySQL or POSTGRES */
# ifdef USEMYSQLVM
# include <mysql/mysql.h>
# define USESQLVM 1
# endif
# ifdef USEPOSTGRESVM
/*
* PostgreSQL routines written by Otmar Lendl < lendl @ nic . at >
*/
# include <postgresql/libpq-fe.h>
# define USESQLVM 1
# endif
# ifndef USESQLVM
static inline int sql_init ( void ) { return 0 ; }
static inline void sql_close ( void ) { }
# endif
1999-11-21 21:15:14 +00:00
# include <pthread.h>
# include "../asterisk.h"
2003-01-30 15:03:20 +00:00
# include "../astconf.h"
1999-11-21 21:15:14 +00:00
# define COMMAND_TIMEOUT 5000
# define VOICEMAIL_CONFIG "voicemail.conf"
# define ASTERISK_USERNAME "asterisk"
# define SENDMAIL " / usr / sbin / sendmail -t"
# define INTRO "vm-intro"
# define MAXMSG 100
# define MAX_OTHER_FORMATS 10
# define VM_SPOOL_DIR AST_SPOOL_DIR " / vm"
2002-03-01 16:54:59 +00:00
# define BASEMAXINLINE 256
# define BASELINELEN 72
# define BASEMAXINLINE 256
# define eol "\r\n"
2003-11-13 01:47:23 +00:00
# define MAX_DATETIME_FORMAT 512
# define DIGITS_DIR AST_SOUNDS " / digits / "
struct baseio {
int iocp ;
int iolen ;
int linelength ;
int ateof ;
unsigned char iobuf [ BASEMAXINLINE ] ;
} ;
struct ast_vm_user {
char context [ 80 ] ;
char mailbox [ 80 ] ;
char password [ 80 ] ;
char fullname [ 80 ] ;
char email [ 80 ] ;
char pager [ 80 ] ;
char serveremail [ 80 ] ;
char zonetag [ 80 ] ;
int attach ;
int alloced ;
struct ast_vm_user * next ;
} ;
struct vm_zone {
char name [ 80 ] ;
char timezone [ 80 ] ;
char msg_format [ 512 ] ;
struct vm_zone * next ;
} ;
1999-11-21 21:15:14 +00:00
2003-12-19 18:06:29 +00:00
struct vm_state {
char curbox [ 80 ] ;
char username [ 80 ] ;
char curdir [ 256 ] ;
char vmbox [ 256 ] ;
char fn [ 256 ] ;
char fn2 [ 256 ] ;
int deleted [ MAXMSG ] ;
int heard [ MAXMSG ] ;
int curmsg ;
int lastmsg ;
int newmessages ;
int oldmessages ;
int starting ;
int repeats ;
} ;
1999-11-21 21:15:14 +00:00
static char * tdesc = " Comedian Mail (Voicemail System) " ;
2001-12-27 11:07:33 +00:00
static char * adapp = " CoMa " ;
static char * adsec = " _AST " ;
static char * addesc = " Comedian Mail " ;
static int adver = 1 ;
2001-05-08 16:21:08 +00:00
static char * synopsis_vm =
" Leave a voicemail message " ;
static char * descrip_vm =
2003-11-13 01:47:23 +00:00
" VoiceMail([s|u|b]extension[@context]): Leaves voicemail for a given \n "
" extension (must be configured in voicemail.conf). If the extension is \n "
" preceded by an 's' then instructions for leaving the message will be \n "
" skipped. If the extension is preceeded by 'u' then the \" unavailable \" \n "
" message will be played (/var/lib/asterisk/sounds/vm/<exten>/unavail) if it \n "
" exists. If the extension is preceeded by a 'b' then the the busy message \n "
" will be played (that is, busy instead of unavail). \n "
2003-11-24 22:14:54 +00:00
" If the requested mailbox does not exist, and there exists a priority \n "
" n + 101, then that priority will be taken next. \n "
2003-11-13 01:47:23 +00:00
" Returns -1 on error or mailbox not found, or if the user hangs up. \n "
" Otherwise, it returns 0. \n " ;
2001-05-08 16:21:08 +00:00
static char * synopsis_vmain =
" Enter voicemail system " ;
static char * descrip_vmain =
2003-11-13 01:47:23 +00:00
" VoiceMailMain([[s]mailbox][@context]): Enters the main voicemail system \n "
" for the checking of voicemail. The mailbox can be passed as the option, \n "
" which will stop the voicemail system from prompting the user for the mailbox. \n "
" If the mailbox is preceded by 's' then the password check will be skipped. If \n "
" a context is specified, logins are considered in that context only. \n "
" Returns -1 if the user hangs up or 0 otherwise. \n " ;
2001-05-08 16:21:08 +00:00
1999-11-21 21:15:14 +00:00
/* Leave a message */
2003-11-13 01:47:23 +00:00
static char * capp = " VoiceMail2 " ;
1999-11-21 21:15:14 +00:00
static char * app = " VoiceMail " ;
/* Check mail, control, etc */
2003-11-13 01:47:23 +00:00
static char * capp2 = " VoiceMailMain2 " ;
1999-11-21 21:15:14 +00:00
static char * app2 = " VoiceMailMain " ;
2003-11-13 01:47:23 +00:00
static ast_mutex_t vmlock = AST_MUTEX_INITIALIZER ;
struct ast_vm_user * users ;
struct ast_vm_user * usersl ;
struct vm_zone * zones = NULL ;
struct vm_zone * zonesl = NULL ;
static int attach_voicemail ;
static int maxsilence ;
static int silencethreshold = 128 ;
static char serveremail [ 80 ] ;
static char vmfmts [ 80 ] ;
static int vmmaxmessage ;
static int maxgreet ;
static int skipms ;
static int maxlogins ;
static char * emailbody = NULL ;
static int pbxskip = 0 ;
static char fromstring [ 100 ] ;
static char emailtitle [ 100 ] ;
1999-11-21 21:15:14 +00:00
STANDARD_LOCAL_USER ;
LOCAL_USER_DECL ;
2003-11-13 01:47:23 +00:00
static void apply_options ( struct ast_vm_user * vmu , char * options )
1999-11-21 21:15:14 +00:00
{
2003-11-13 01:47:23 +00:00
/* Destructively Parse options and apply */
char * stringp = ast_strdupa ( options ) ;
char * s ;
char * var , * value ;
while ( ( s = strsep ( & stringp , " | " ) ) ) {
value = s ;
if ( ( var = strsep ( & value , " = " ) ) & & value ) {
if ( ! strcasecmp ( var , " attach " ) ) {
if ( ast_true ( value ) )
vmu - > attach = 1 ;
else
vmu - > attach = 0 ;
} else if ( ! strcasecmp ( var , " serveremail " ) ) {
strncpy ( vmu - > serveremail , value , sizeof ( vmu - > serveremail ) - 1 ) ;
} else if ( ! strcasecmp ( var , " tz " ) ) {
strncpy ( vmu - > zonetag , value , sizeof ( vmu - > zonetag ) - 1 ) ;
}
}
}
1999-11-21 21:15:14 +00:00
}
2001-08-05 21:46:13 +00:00
2003-11-13 01:47:23 +00:00
# ifdef USEMYSQLVM
# include "mysql-vm-routines.h"
# endif
# ifdef USEPOSTGRESVM
PGconn * dbhandler ;
char dboption [ 256 ] ;
ast_mutex_t postgreslock ;
static int sql_init ( void )
1999-11-21 21:15:14 +00:00
{
2003-11-13 01:47:23 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Logging into postgres database: %s \n " , dboption ) ;
/* fprintf(stderr,"Logging into postgres database: %s\n", dboption); */
dbhandler = PQconnectdb ( dboption ) ;
if ( PQstatus ( dbhandler ) = = CONNECTION_BAD ) {
ast_log ( LOG_WARNING , " Error Logging into database %s: %s \n " , dboption , PQerrorMessage ( dbhandler ) ) ;
return ( - 1 ) ;
}
ast_mutex_init ( & postgreslock ) ;
/* fprintf(stderr,"postgres login OK\n"); */
return ( 0 ) ;
}
static void sql_close ( void )
{
PQfinish ( dbhandler ) ;
}
static struct ast_vm_user * find_user ( struct ast_vm_user * ivm , char * context , char * mailbox )
{
PGresult * PGSQLres ;
int numFields , i ;
char * fname ;
char query [ 240 ] ;
char options [ 160 ] = " " ;
struct ast_vm_user * retval ;
retval = malloc ( sizeof ( struct ast_vm_user ) ) ;
/* fprintf(stderr,"postgres find_user:\n"); */
if ( retval ) {
* retval - > mailbox = ' \0 ' ;
* retval - > context = ' \0 ' ;
* retval - > password = ' \0 ' ;
* retval - > fullname = ' \0 ' ;
* retval - > email = ' \0 ' ;
* retval - > pager = ' \0 ' ;
* retval - > serveremail = ' \0 ' ;
retval - > attach = - 1 ;
retval - > alloced = 1 ;
retval - > next = NULL ;
if ( mailbox ) {
strcpy ( retval - > mailbox , mailbox ) ;
}
if ( context ) {
strcpy ( retval - > context , context ) ;
}
2003-12-04 23:19:26 +00:00
else
{
strcpy ( retval - > context , " default " ) ;
}
2003-11-13 01:47:23 +00:00
if ( * retval - > context ) {
sprintf ( query , " SELECT password,fullname,email,pager,options FROM voicemail WHERE context='%s' AND mailbox='%s' " , context , mailbox ) ;
} else {
2003-12-04 23:19:26 +00:00
sprintf ( query , " SELECT password,fullname,email,pager,options FROM voicemail WHERE context='default' AND mailbox='%s' " , mailbox ) ;
2003-11-13 01:47:23 +00:00
}
/* fprintf(stderr,"postgres find_user: query = %s\n",query); */
ast_mutex_lock ( & postgreslock ) ;
PGSQLres = PQexec ( dbhandler , query ) ;
if ( PGSQLres ! = NULL ) {
if ( PQresultStatus ( PGSQLres ) = = PGRES_BAD_RESPONSE | |
PQresultStatus ( PGSQLres ) = = PGRES_NONFATAL_ERROR | |
PQresultStatus ( PGSQLres ) = = PGRES_FATAL_ERROR ) {
ast_log ( LOG_WARNING , " PGSQL_query: Query Error (%s) Calling PQreset \n " , PQcmdStatus ( PGSQLres ) ) ;
PQclear ( PGSQLres ) ;
PQreset ( dbhandler ) ;
ast_mutex_unlock ( & postgreslock ) ;
free ( retval ) ;
return ( NULL ) ;
} else {
numFields = PQnfields ( PGSQLres ) ;
/* fprintf(stderr,"postgres find_user: query found %d rows with %d fields\n",PQntuples(PGSQLres), numFields); */
if ( PQntuples ( PGSQLres ) ! = 1 ) {
ast_log ( LOG_WARNING , " PGSQL_query: Did not find a unique mailbox for %s \n " , mailbox ) ;
PQclear ( PGSQLres ) ;
ast_mutex_unlock ( & postgreslock ) ;
free ( retval ) ;
return ( NULL ) ;
}
for ( i = 0 ; i < numFields ; i + + ) {
fname = PQfname ( PGSQLres , i ) ;
if ( ! strcmp ( fname , " password " ) ) {
strncpy ( retval - > password , PQgetvalue ( PGSQLres , 0 , i ) , sizeof ( retval - > password ) - 1 ) ;
} else if ( ! strcmp ( fname , " fullname " ) ) {
strncpy ( retval - > fullname , PQgetvalue ( PGSQLres , 0 , i ) , sizeof ( retval - > fullname ) - 1 ) ;
} else if ( ! strcmp ( fname , " email " ) ) {
strncpy ( retval - > email , PQgetvalue ( PGSQLres , 0 , i ) , sizeof ( retval - > email ) - 1 ) ;
} else if ( ! strcmp ( fname , " pager " ) ) {
strncpy ( retval - > pager , PQgetvalue ( PGSQLres , 0 , i ) , sizeof ( retval - > pager ) - 1 ) ;
} else if ( ! strcmp ( fname , " options " ) ) {
strncpy ( options , PQgetvalue ( PGSQLres , 0 , i ) , sizeof ( options ) - 1 ) ;
apply_options ( retval , options ) ;
}
}
}
PQclear ( PGSQLres ) ;
ast_mutex_unlock ( & postgreslock ) ;
return ( retval ) ;
}
else {
ast_log ( LOG_WARNING , " PGSQL_query: Connection Error (%s) \n " , PQerrorMessage ( dbhandler ) ) ;
ast_mutex_unlock ( & postgreslock ) ;
free ( retval ) ;
return ( NULL ) ;
}
/* not reached */
} /* malloc() retval */
return ( NULL ) ;
}
static void vm_change_password ( struct ast_vm_user * vmu , char * password )
{
char query [ 400 ] ;
if ( * vmu - > context ) {
sprintf ( query , " UPDATE voicemail SET password='%s' WHERE context='%s' AND mailbox='%s' AND (password='%s' OR password IS NULL) " , password , vmu - > context , vmu - > mailbox , vmu - > password ) ;
} else {
sprintf ( query , " UPDATE voicemail SET password='%s' WHERE mailbox='%s' AND (password='%s' OR password IS NULL) " , password , vmu - > mailbox , vmu - > password ) ;
}
/* fprintf(stderr,"postgres change_password: query = %s\n",query); */
ast_mutex_lock ( & postgreslock ) ;
PQexec ( dbhandler , query ) ;
strcpy ( vmu - > password , password ) ;
ast_mutex_unlock ( & postgreslock ) ;
}
static void reset_user_pw ( char * context , char * mailbox , char * password )
{
char query [ 320 ] ;
if ( context ) {
sprintf ( query , " UPDATE voicemail SET password='%s' WHERE context='%s' AND mailbox='%s' " , password , context , mailbox ) ;
} else {
sprintf ( query , " UPDATE voicemail SET password='%s' WHERE mailbox='%s' " , password , mailbox ) ;
}
ast_mutex_lock ( & postgreslock ) ;
/* fprintf(stderr,"postgres reset_user_pw: query = %s\n",query); */
PQexec ( dbhandler , query ) ;
ast_mutex_unlock ( & postgreslock ) ;
}
# endif /* Postgres */
# ifndef USESQLVM
static struct ast_vm_user * find_user ( struct ast_vm_user * ivm , char * context , char * mailbox )
{
/* This function could be made to generate one from a database, too */
struct ast_vm_user * vmu = NULL , * cur ;
ast_mutex_lock ( & vmlock ) ;
cur = users ;
while ( cur ) {
if ( ( ! context | | ! strcasecmp ( context , cur - > context ) ) & &
( ! strcasecmp ( mailbox , cur - > mailbox ) ) )
break ;
cur = cur - > next ;
}
if ( cur ) {
if ( ivm )
vmu = ivm ;
else
/* Make a copy, so that on a reload, we have no race */
vmu = malloc ( sizeof ( struct ast_vm_user ) ) ;
if ( vmu ) {
memcpy ( vmu , cur , sizeof ( struct ast_vm_user ) ) ;
if ( ivm )
vmu - > alloced = 0 ;
else
vmu - > alloced = 1 ;
vmu - > next = NULL ;
}
}
ast_mutex_unlock ( & vmlock ) ;
return vmu ;
}
static int reset_user_pw ( char * context , char * mailbox , char * newpass )
{
/* This function could be made to generate one from a database, too */
struct ast_vm_user * cur ;
int res = - 1 ;
ast_mutex_lock ( & vmlock ) ;
cur = users ;
while ( cur ) {
if ( ( ! context | | ! strcasecmp ( context , cur - > context ) ) & &
( ! strcasecmp ( mailbox , cur - > mailbox ) ) )
break ;
cur = cur - > next ;
}
if ( cur ) {
strncpy ( cur - > password , newpass , sizeof ( cur - > password ) - 1 ) ;
res = 0 ;
}
ast_mutex_unlock ( & vmlock ) ;
return res ;
1999-11-21 21:15:14 +00:00
}
2003-11-13 01:47:23 +00:00
static void vm_change_password ( struct ast_vm_user * vmu , char * newpassword )
2002-07-31 20:34:22 +00:00
{
/* There's probably a better way of doing this. */
/* That's why I've put the password change in a separate function. */
2003-11-13 01:47:23 +00:00
/* This could also be done with a database function */
2002-07-31 20:34:22 +00:00
FILE * configin ;
FILE * configout ;
char inbuf [ 256 ] ;
char orig [ 256 ] ;
2003-01-30 15:03:20 +00:00
char tmpin [ AST_CONFIG_MAX_PATH ] ;
char tmpout [ AST_CONFIG_MAX_PATH ] ;
2002-07-31 20:34:22 +00:00
char * user , * pass , * rest , * trim ;
2003-11-13 01:47:23 +00:00
snprintf ( ( char * ) tmpin , sizeof ( tmpin ) - 1 , " %s/voicemail.conf " , ( char * ) ast_config_AST_CONFIG_DIR ) ;
snprintf ( ( char * ) tmpout , sizeof ( tmpout ) - 1 , " %s/voicemail.conf.new " , ( char * ) ast_config_AST_CONFIG_DIR ) ;
2003-01-30 15:03:20 +00:00
configin = fopen ( ( char * ) tmpin , " r " ) ;
2003-11-13 01:47:23 +00:00
if ( configin )
configout = fopen ( ( char * ) tmpout , " w+ " ) ;
else
configout = NULL ;
if ( ! configin | | ! configout ) {
if ( configin )
fclose ( configin ) ;
else
ast_log ( LOG_WARNING , " Warning: Unable to open '%s' for reading: %s \n " , tmpin , strerror ( errno ) ) ;
if ( configout )
fclose ( configout ) ;
else
ast_log ( LOG_WARNING , " Warning: Unable to open '%s' for writing: %s \n " , tmpout , strerror ( errno ) ) ;
return ;
}
2002-07-31 20:34:22 +00:00
while ( ! feof ( configin ) ) {
/* Read in the line */
fgets ( inbuf , sizeof ( inbuf ) , configin ) ;
if ( ! feof ( configin ) ) {
/* Make a backup of it */
memcpy ( orig , inbuf , sizeof ( orig ) ) ;
/* Strip trailing \n and comment */
inbuf [ strlen ( inbuf ) - 1 ] = ' \0 ' ;
user = strchr ( inbuf , ' ; ' ) ;
if ( user )
* user = ' \0 ' ;
user = inbuf ;
while ( * user < 33 )
user + + ;
pass = strchr ( user , ' = ' ) ;
if ( pass > user ) {
trim = pass - 1 ;
while ( * trim & & * trim < 33 ) {
* trim = ' \0 ' ;
trim - - ;
}
}
if ( pass ) {
* pass = ' \0 ' ;
pass + + ;
if ( * pass = = ' > ' )
pass + + ;
while ( * pass & & * pass < 33 )
pass + + ;
}
if ( pass ) {
rest = strchr ( pass , ' , ' ) ;
if ( rest ) {
* rest = ' \0 ' ;
rest + + ;
}
} else
rest = NULL ;
2003-11-13 01:47:23 +00:00
if ( user & & pass & & * user & & * pass & & ! strcmp ( user , vmu - > mailbox ) & & ! strcmp ( pass , vmu - > password ) ) {
2002-07-31 20:34:22 +00:00
/* This is the line */
if ( rest ) {
2003-11-13 01:47:23 +00:00
fprintf ( configout , " %s => %s,%s \n " , vmu - > mailbox , newpassword , rest ) ;
2002-07-31 20:34:22 +00:00
} else {
2003-11-13 01:47:23 +00:00
fprintf ( configout , " %s => %s \n " , vmu - > mailbox , newpassword ) ;
2002-07-31 20:34:22 +00:00
}
} else {
/* Put it back like it was */
fprintf ( configout , orig ) ;
}
}
}
fclose ( configin ) ;
fclose ( configout ) ;
2003-01-30 15:03:20 +00:00
unlink ( ( char * ) tmpin ) ;
rename ( ( char * ) tmpout , ( char * ) tmpin ) ;
2003-11-13 01:47:23 +00:00
reset_user_pw ( vmu - > context , vmu - > mailbox , newpassword ) ;
strncpy ( vmu - > password , newpassword , sizeof ( vmu - > password ) - 1 ) ;
}
# endif
static int make_dir ( char * dest , int len , char * context , char * ext , char * mailbox )
{
return snprintf ( dest , len , " %s/voicemail/%s/%s/%s " , ( char * ) ast_config_AST_SPOOL_DIR , context , ext , mailbox ) ;
}
static int make_file ( char * dest , int len , char * dir , int num )
{
return snprintf ( dest , len , " %s/msg%04d " , dir , num ) ;
2002-07-31 20:34:22 +00:00
}
2002-03-01 16:54:59 +00:00
static int
2003-11-13 01:47:23 +00:00
inbuf ( struct baseio * bio , FILE * fi )
2002-03-01 16:54:59 +00:00
{
int l ;
2003-11-13 01:47:23 +00:00
if ( bio - > ateof )
2002-03-01 16:54:59 +00:00
return 0 ;
2003-11-13 01:47:23 +00:00
if ( ( l = fread ( bio - > iobuf , 1 , BASEMAXINLINE , fi ) ) < = 0 ) {
2002-03-01 16:54:59 +00:00
if ( ferror ( fi ) )
return - 1 ;
2003-11-13 01:47:23 +00:00
bio - > ateof = 1 ;
2002-03-01 16:54:59 +00:00
return 0 ;
}
2003-11-13 01:47:23 +00:00
bio - > iolen = l ;
bio - > iocp = 0 ;
2002-03-01 16:54:59 +00:00
return 1 ;
}
static int
2003-11-13 01:47:23 +00:00
inchar ( struct baseio * bio , FILE * fi )
2002-03-01 16:54:59 +00:00
{
2003-11-13 01:47:23 +00:00
if ( bio - > iocp > = bio - > iolen )
if ( ! inbuf ( bio , fi ) )
2002-03-01 16:54:59 +00:00
return EOF ;
2003-11-13 01:47:23 +00:00
return bio - > iobuf [ bio - > iocp + + ] ;
2002-03-01 16:54:59 +00:00
}
static int
2003-11-13 01:47:23 +00:00
ochar ( struct baseio * bio , int c , FILE * so )
2002-03-01 16:54:59 +00:00
{
2003-11-13 01:47:23 +00:00
if ( bio - > linelength > = BASELINELEN ) {
2002-03-01 16:54:59 +00:00
if ( fputs ( eol , so ) = = EOF )
return - 1 ;
2003-11-13 01:47:23 +00:00
bio - > linelength = 0 ;
2002-03-01 16:54:59 +00:00
}
if ( putc ( ( ( unsigned char ) c ) , so ) = = EOF )
return - 1 ;
2003-11-13 01:47:23 +00:00
bio - > linelength + + ;
2002-03-01 16:54:59 +00:00
return 1 ;
}
static int base_encode ( char * filename , FILE * so )
{
unsigned char dtable [ BASEMAXINLINE ] ;
int i , hiteof = 0 ;
FILE * fi ;
2003-11-13 01:47:23 +00:00
struct baseio bio ;
2002-03-01 16:54:59 +00:00
2003-11-13 01:47:23 +00:00
memset ( & bio , 0 , sizeof ( bio ) ) ;
bio . iocp = BASEMAXINLINE ;
2002-03-01 16:54:59 +00:00
if ( ! ( fi = fopen ( filename , " rb " ) ) ) {
ast_log ( LOG_WARNING , " Failed to open log file: %s: %s \n " , filename , strerror ( errno ) ) ;
return - 1 ;
}
for ( i = 0 ; i < 9 ; i + + ) {
dtable [ i ] = ' A ' + i ;
dtable [ i + 9 ] = ' J ' + i ;
dtable [ 26 + i ] = ' a ' + i ;
dtable [ 26 + i + 9 ] = ' j ' + i ;
}
for ( i = 0 ; i < 8 ; i + + ) {
dtable [ i + 18 ] = ' S ' + i ;
dtable [ 26 + i + 18 ] = ' s ' + i ;
}
for ( i = 0 ; i < 10 ; i + + ) {
dtable [ 52 + i ] = ' 0 ' + i ;
}
dtable [ 62 ] = ' + ' ;
dtable [ 63 ] = ' / ' ;
while ( ! hiteof ) {
unsigned char igroup [ 3 ] , ogroup [ 4 ] ;
int c , n ;
igroup [ 0 ] = igroup [ 1 ] = igroup [ 2 ] = 0 ;
for ( n = 0 ; n < 3 ; n + + ) {
2003-11-13 01:47:23 +00:00
if ( ( c = inchar ( & bio , fi ) ) = = EOF ) {
2002-03-01 16:54:59 +00:00
hiteof = 1 ;
break ;
}
igroup [ n ] = ( unsigned char ) c ;
}
if ( n > 0 ) {
ogroup [ 0 ] = dtable [ igroup [ 0 ] > > 2 ] ;
ogroup [ 1 ] = dtable [ ( ( igroup [ 0 ] & 3 ) < < 4 ) | ( igroup [ 1 ] > > 4 ) ] ;
ogroup [ 2 ] = dtable [ ( ( igroup [ 1 ] & 0xF ) < < 2 ) | ( igroup [ 2 ] > > 6 ) ] ;
ogroup [ 3 ] = dtable [ igroup [ 2 ] & 0x3F ] ;
if ( n < 3 ) {
ogroup [ 3 ] = ' = ' ;
if ( n < 2 )
ogroup [ 2 ] = ' = ' ;
}
for ( i = 0 ; i < 4 ; i + + )
2003-11-13 01:47:23 +00:00
ochar ( & bio , ogroup [ i ] , so ) ;
2002-03-01 16:54:59 +00:00
}
}
if ( fputs ( eol , so ) = = EOF )
return 0 ;
fclose ( fi ) ;
return 1 ;
}
2003-11-13 01:47:23 +00:00
static int sendmail ( char * srcemail , struct ast_vm_user * vmu , int msgnum , char * mailbox , char * callerid , char * attach , char * format , long duration , int attach_user_voicemail )
1999-11-21 21:15:14 +00:00
{
FILE * p ;
char date [ 256 ] ;
char host [ 256 ] ;
2001-08-05 21:46:13 +00:00
char who [ 256 ] ;
2002-03-01 16:54:59 +00:00
char bound [ 256 ] ;
char fname [ 256 ] ;
2002-06-28 15:21:23 +00:00
char dur [ 256 ] ;
1999-11-21 21:15:14 +00:00
time_t t ;
2003-03-31 03:19:34 +00:00
struct tm tm ;
2003-11-13 01:47:23 +00:00
struct vm_zone * the_zone = NULL ;
if ( ! strcmp ( format , " wav49 " ) )
format = " WAV " ;
ast_log ( LOG_DEBUG , " Attaching file '%s', format '%s', uservm is '%d', global is %d \n " , attach , format , attach_user_voicemail , attach_voicemail ) ;
1999-11-21 21:15:14 +00:00
p = popen ( SENDMAIL , " w " ) ;
if ( p ) {
2003-01-30 15:03:20 +00:00
gethostname ( host , sizeof ( host ) ) ;
2001-08-05 21:46:13 +00:00
if ( strchr ( srcemail , ' @ ' ) )
2001-12-27 11:07:33 +00:00
strncpy ( who , srcemail , sizeof ( who ) - 1 ) ;
2001-08-05 21:46:13 +00:00
else {
snprintf ( who , sizeof ( who ) , " %s@%s " , srcemail , host ) ;
}
2002-07-31 20:34:22 +00:00
snprintf ( dur , sizeof ( dur ) , " %ld:%02ld " , duration / 60 , duration % 60 ) ;
1999-11-21 21:15:14 +00:00
time ( & t ) ;
2003-11-13 01:47:23 +00:00
/* Does this user have a timezone specified? */
if ( strlen ( vmu - > zonetag ) ) {
/* Find the zone in the list */
struct vm_zone * z ;
z = zones ;
while ( z ) {
if ( ! strcmp ( z - > name , vmu - > zonetag ) ) {
the_zone = z ;
break ;
}
z = z - > next ;
}
}
if ( the_zone )
ast_localtime ( & t , & tm , the_zone - > timezone ) ;
else
ast_localtime ( & t , & tm , NULL ) ;
2003-03-31 03:19:34 +00:00
strftime ( date , sizeof ( date ) , " %a, %d %b %Y %H:%M:%S %z " , & tm ) ;
1999-11-21 21:15:14 +00:00
fprintf ( p , " Date: %s \n " , date ) ;
2003-11-13 01:47:23 +00:00
if ( * fromstring )
fprintf ( p , " From: %s <%s> \n " , fromstring , who ) ;
else
fprintf ( p , " From: Asterisk PBX <%s> \n " , who ) ;
fprintf ( p , " To: %s <%s> \n " , vmu - > fullname , vmu - > email ) ;
if ( * emailtitle )
{
fprintf ( p , emailtitle , msgnum , mailbox ) ;
fprintf ( p , " \n " ) ;
}
else
if ( pbxskip )
fprintf ( p , " Subject: New message %d in mailbox %s \n " , msgnum + 1 , mailbox ) ;
else
fprintf ( p , " Subject: [PBX]: New message %d in mailbox %s \n " , msgnum + 1 , mailbox ) ;
2002-03-01 16:54:59 +00:00
fprintf ( p , " Message-ID: <Asterisk-%d-%s-%d@%s> \n " , msgnum , mailbox , getpid ( ) , host ) ;
fprintf ( p , " MIME-Version: 1.0 \n " ) ;
2003-11-13 01:47:23 +00:00
if ( attach_user_voicemail ) {
2003-01-30 15:03:20 +00:00
// Something unique.
snprintf ( bound , sizeof ( bound ) , " Boundary=%d%s%d " , msgnum , mailbox , getpid ( ) ) ;
2002-03-01 16:54:59 +00:00
2003-01-30 15:03:20 +00:00
fprintf ( p , " Content-Type: MULTIPART/MIXED; BOUNDARY= \" %s \" \n \n \n " , bound ) ;
2002-03-01 16:54:59 +00:00
2003-01-30 15:03:20 +00:00
fprintf ( p , " --%s \n " , bound ) ;
}
2003-11-13 01:47:23 +00:00
fprintf ( p , " Content-Type: TEXT/PLAIN; charset=US-ASCII \n \n " ) ;
strftime ( date , sizeof ( date ) , " %A, %B %d, %Y at %r " , & tm ) ;
if ( emailbody ) {
struct ast_channel * ast = ast_channel_alloc ( 0 ) ;
if ( ast ) {
char * passdata ;
int vmlen = strlen ( emailbody ) * 3 + 200 ;
if ( ( passdata = alloca ( vmlen ) ) ) {
memset ( passdata , 0 , vmlen ) ;
pbx_builtin_setvar_helper ( ast , " VM_NAME " , vmu - > fullname ) ;
pbx_builtin_setvar_helper ( ast , " VM_DUR " , dur ) ;
sprintf ( passdata , " %d " , msgnum ) ;
pbx_builtin_setvar_helper ( ast , " VM_MSGNUM " , passdata ) ;
pbx_builtin_setvar_helper ( ast , " VM_MAILBOX " , mailbox ) ;
pbx_builtin_setvar_helper ( ast , " VM_CALLERID " , ( callerid ? callerid : " an unknown caller " ) ) ;
pbx_builtin_setvar_helper ( ast , " VM_DATE " , date ) ;
pbx_substitute_variables_helper ( ast , emailbody , passdata , vmlen ) ;
fprintf ( p , " %s \n " , passdata ) ;
} else ast_log ( LOG_WARNING , " Cannot allocate workspace for variable substitution \n " ) ;
ast_channel_free ( ast ) ;
} else ast_log ( LOG_WARNING , " Cannot allocate the channel for variables substitution \n " ) ;
} else {
2003-01-30 15:03:20 +00:00
fprintf ( p , " Dear %s: \n \n \t Just wanted to let you know you were just left a %s long message (number %d) \n "
2002-03-01 16:54:59 +00:00
2003-11-13 01:47:23 +00:00
" in mailbox %s from %s, on %s so you might \n "
" want to check it when you get a chance. Thanks! \n \n \t \t \t \t --Asterisk \n \n " , vmu - > fullname ,
dur , msgnum + 1 , mailbox , ( callerid ? callerid : " an unknown caller " ) , date ) ;
}
if ( attach_user_voicemail ) {
2003-01-30 15:03:20 +00:00
fprintf ( p , " --%s \n " , bound ) ;
2003-11-17 06:16:41 +00:00
fprintf ( p , " Content-Type: audio/x-%s; name= \" msg%04d.%s \" \n " , format , msgnum , format ) ;
2003-01-30 15:03:20 +00:00
fprintf ( p , " Content-Transfer-Encoding: BASE64 \n " ) ;
fprintf ( p , " Content-Description: Voicemail sound attachment. \n " ) ;
fprintf ( p , " Content-Disposition: attachment; filename= \" msg%04d.%s \" \n \n " , msgnum , format ) ;
snprintf ( fname , sizeof ( fname ) , " %s.%s " , attach , format ) ;
base_encode ( fname , p ) ;
fprintf ( p , " \n \n --%s-- \n . \n " , bound ) ;
}
1999-11-21 21:15:14 +00:00
pclose ( p ) ;
} else {
ast_log ( LOG_WARNING , " Unable to launch '%s' \n " , SENDMAIL ) ;
return - 1 ;
}
return 0 ;
}
2003-11-13 01:47:23 +00:00
static int sendpage ( char * srcemail , char * pager , int msgnum , char * mailbox , char * callerid , long duration , struct ast_vm_user * vmu )
2003-04-11 17:37:35 +00:00
{
FILE * p ;
char date [ 256 ] ;
char host [ 256 ] ;
char who [ 256 ] ;
char dur [ 256 ] ;
time_t t ;
struct tm tm ;
2003-11-13 01:47:23 +00:00
struct vm_zone * the_zone = NULL ;
2003-04-11 17:37:35 +00:00
p = popen ( SENDMAIL , " w " ) ;
if ( p ) {
gethostname ( host , sizeof ( host ) ) ;
if ( strchr ( srcemail , ' @ ' ) )
strncpy ( who , srcemail , sizeof ( who ) - 1 ) ;
else {
snprintf ( who , sizeof ( who ) , " %s@%s " , srcemail , host ) ;
}
snprintf ( dur , sizeof ( dur ) , " %ld:%02ld " , duration / 60 , duration % 60 ) ;
time ( & t ) ;
2003-11-13 01:47:23 +00:00
/* Does this user have a timezone specified? */
if ( strlen ( vmu - > zonetag ) ) {
/* Find the zone in the list */
struct vm_zone * z ;
z = zones ;
while ( z ) {
if ( ! strcmp ( z - > name , vmu - > zonetag ) ) {
the_zone = z ;
break ;
}
z = z - > next ;
}
}
if ( the_zone )
ast_localtime ( & t , & tm , the_zone - > timezone ) ;
else
ast_localtime ( & t , & tm , NULL ) ;
2003-04-11 17:37:35 +00:00
strftime ( date , sizeof ( date ) , " %a, %d %b %Y %H:%M:%S %z " , & tm ) ;
fprintf ( p , " Date: %s \n " , date ) ;
fprintf ( p , " From: Asterisk PBX <%s> \n " , who ) ;
fprintf ( p , " To: %s \n " , pager ) ;
2003-05-01 14:32:15 +00:00
fprintf ( p , " Subject: New VM \n \n " ) ;
2003-04-11 17:37:35 +00:00
strftime ( date , sizeof ( date ) , " %A, %B %d, %Y at %r " , & tm ) ;
2003-05-01 14:32:15 +00:00
fprintf ( p , " New %s long msg in box %s \n "
2003-04-11 17:37:35 +00:00
" from %s, on %s " , dur , mailbox , ( callerid ? callerid : " unknown " ) , date ) ;
pclose ( p ) ;
} else {
ast_log ( LOG_WARNING , " Unable to launch '%s' \n " , SENDMAIL ) ;
return - 1 ;
}
return 0 ;
}
2001-05-08 16:21:08 +00:00
static int get_date ( char * s , int len )
{
2003-03-31 03:19:34 +00:00
struct tm tm ;
2001-05-08 16:21:08 +00:00
time_t t ;
t = time ( 0 ) ;
2003-03-31 03:19:34 +00:00
localtime_r ( & t , & tm ) ;
return strftime ( s , len , " %a %b %e %r %Z %Y " , & tm ) ;
2001-05-08 16:21:08 +00:00
}
2003-11-13 01:47:23 +00:00
static int invent_message ( struct ast_channel * chan , char * context , char * ext , int busy , char * ecodes )
2001-12-27 11:07:33 +00:00
{
int res ;
2002-06-28 15:21:23 +00:00
char fn [ 256 ] ;
2003-11-13 01:47:23 +00:00
snprintf ( fn , sizeof ( fn ) , " voicemail/%s/%s/greet " , context , ext ) ;
2002-06-28 15:21:23 +00:00
if ( ast_fileexists ( fn , NULL , NULL ) > 0 ) {
res = ast_streamfile ( chan , fn , chan - > language ) ;
if ( res )
return - 1 ;
2003-01-30 15:03:20 +00:00
res = ast_waitstream ( chan , ecodes ) ;
2002-06-28 15:21:23 +00:00
if ( res )
return res ;
} else {
res = ast_streamfile ( chan , " vm-theperson " , chan - > language ) ;
if ( res )
return - 1 ;
2003-01-30 15:03:20 +00:00
res = ast_waitstream ( chan , ecodes ) ;
2002-06-28 15:21:23 +00:00
if ( res )
return res ;
2003-01-30 15:03:20 +00:00
res = ast_say_digit_str ( chan , ext , ecodes , chan - > language ) ;
2002-06-28 15:21:23 +00:00
if ( res )
return res ;
}
2001-12-27 11:07:33 +00:00
if ( busy )
res = ast_streamfile ( chan , " vm-isonphone " , chan - > language ) ;
else
res = ast_streamfile ( chan , " vm-isunavail " , chan - > language ) ;
if ( res )
return - 1 ;
2003-01-30 15:03:20 +00:00
res = ast_waitstream ( chan , ecodes ) ;
2001-12-27 11:07:33 +00:00
return res ;
}
2003-11-13 01:47:23 +00:00
static int play_and_wait ( struct ast_channel * chan , char * fn )
1999-11-21 21:15:14 +00:00
{
2003-11-13 01:47:23 +00:00
int d ;
d = ast_streamfile ( chan , fn , chan - > language ) ;
if ( d )
return d ;
d = ast_waitstream ( chan , AST_DIGIT_ANY ) ;
2003-11-13 05:43:07 +00:00
ast_stopstream ( chan ) ;
2003-11-13 01:47:23 +00:00
return d ;
}
2003-12-19 18:06:29 +00:00
static int play_and_prepend ( struct ast_channel * chan , char * playfile , char * recordfile , int maxtime , char * fmt )
{
char d , * fmts ;
char comment [ 256 ] ;
int x , fmtcnt = 1 , res = - 1 , outmsg = 0 ;
struct ast_frame * f ;
struct ast_filestream * others [ MAX_OTHER_FORMATS ] ;
struct ast_filestream * realfiles [ MAX_OTHER_FORMATS ] ;
char * sfmt [ MAX_OTHER_FORMATS ] ;
char * stringp = NULL ;
time_t start , end ;
struct ast_dsp * sildet ; /* silence detector dsp */
int totalsilence = 0 ;
int dspsilence = 0 ;
int gotsilence = 0 ; /* did we timeout for silence? */
int rfmt = 0 ;
char prependfile [ 80 ] ;
ast_log ( LOG_DEBUG , " play_and_preped: %s, %s, '%s' \n " , playfile ? playfile : " <None> " , recordfile , fmt ) ;
snprintf ( comment , sizeof ( comment ) , " Playing %s, Recording to: %s on %s \n " , playfile ? playfile : " <None> " , recordfile , chan - > name ) ;
if ( playfile ) {
d = play_and_wait ( chan , playfile ) ;
if ( d > - 1 )
d = ast_streamfile ( chan , " beep " , chan - > language ) ;
if ( ! d )
d = ast_waitstream ( chan , " " ) ;
if ( d < 0 )
return - 1 ;
}
strncpy ( prependfile , recordfile , sizeof ( prependfile ) - 1 ) ;
strcat ( prependfile , " -prepend " ) ;
fmts = ast_strdupa ( fmt ) ;
stringp = fmts ;
strsep ( & stringp , " | " ) ;
ast_log ( LOG_DEBUG , " Recording Formats: sfmts=%s \n " , fmts ) ;
sfmt [ 0 ] = ast_strdupa ( fmts ) ;
while ( ( fmt = strsep ( & stringp , " | " ) ) ) {
if ( fmtcnt > MAX_OTHER_FORMATS - 1 ) {
ast_log ( LOG_WARNING , " Please increase MAX_OTHER_FORMATS in app_voicemail.c \n " ) ;
break ;
}
sfmt [ fmtcnt + + ] = ast_strdupa ( fmt ) ;
}
if ( maxtime )
time ( & start ) ;
for ( x = 0 ; x < fmtcnt ; x + + ) {
others [ x ] = ast_writefile ( prependfile , sfmt [ x ] , comment , O_TRUNC , 0 , 0700 ) ;
ast_verbose ( VERBOSE_PREFIX_3 " x=%i, open writing: %s format: %s, %p \n " , x , prependfile , sfmt [ x ] , others [ x ] ) ;
if ( ! others [ x ] ) {
break ;
}
}
sildet = ast_dsp_new ( ) ; //Create the silence detector
if ( ! sildet ) {
ast_log ( LOG_WARNING , " Unable to create silence detector :( \n " ) ;
return - 1 ;
}
ast_dsp_set_threshold ( sildet , silencethreshold ) ;
if ( maxsilence > 0 ) {
rfmt = chan - > readformat ;
res = ast_set_read_format ( chan , AST_FORMAT_SLINEAR ) ;
if ( res < 0 ) {
ast_log ( LOG_WARNING , " Unable to set to linear mode, giving up \n " ) ;
return - 1 ;
}
}
if ( x = = fmtcnt ) {
/* Loop forever, writing the packets we read to the writer(s), until
we read a # or get a hangup */
f = NULL ;
for ( ; ; ) {
res = ast_waitfor ( chan , 2000 ) ;
if ( ! res ) {
ast_log ( LOG_DEBUG , " One waitfor failed, trying another \n " ) ;
/* Try one more time in case of masq */
res = ast_waitfor ( chan , 2000 ) ;
if ( ! res ) {
ast_log ( LOG_WARNING , " No audio available on %s?? \n " , chan - > name ) ;
res = - 1 ;
}
}
if ( res < 0 ) {
f = NULL ;
break ;
}
f = ast_read ( chan ) ;
if ( ! f )
break ;
if ( f - > frametype = = AST_FRAME_VOICE ) {
/* write each format */
for ( x = 0 ; x < fmtcnt ; x + + ) {
if ( ! others [ x ] )
break ;
res = ast_writestream ( others [ x ] , f ) ;
}
/* Silence Detection */
if ( maxsilence > 0 ) {
dspsilence = 0 ;
ast_dsp_silence ( sildet , f , & dspsilence ) ;
if ( dspsilence )
totalsilence = dspsilence ;
else
totalsilence = 0 ;
if ( totalsilence > maxsilence ) {
/* Ended happily with silence */
ast_frfree ( f ) ;
gotsilence = 1 ;
outmsg = 2 ;
break ;
}
}
/* Exit on any error */
if ( res ) {
ast_log ( LOG_WARNING , " Error writing frame \n " ) ;
ast_frfree ( f ) ;
break ;
}
} else if ( f - > frametype = = AST_FRAME_VIDEO ) {
/* Write only once */
ast_writestream ( others [ 0 ] , f ) ;
} else if ( f - > frametype = = AST_FRAME_DTMF ) {
/* stop recording with any digit */
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " User ended message by pressing %c \n " , f - > subclass ) ;
res = f - > subclass ;
outmsg = 2 ;
ast_frfree ( f ) ;
break ;
}
if ( maxtime ) {
time ( & end ) ;
if ( maxtime < ( end - start ) ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Took too long, cutting it short... \n " ) ;
res = ' t ' ;
ast_frfree ( f ) ;
break ;
}
}
ast_frfree ( f ) ;
}
if ( ! f ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " User hung up \n " ) ;
res = - 1 ;
outmsg = 1 ;
2003-12-22 18:22:21 +00:00
#if 0
2003-12-19 18:06:29 +00:00
/* delete all the prepend files */
for ( x = 0 ; x < fmtcnt ; x + + ) {
if ( ! others [ x ] )
break ;
ast_closestream ( others [ x ] ) ;
ast_filedelete ( prependfile , sfmt [ x ] ) ;
}
2003-12-22 18:22:21 +00:00
# endif
2003-12-19 18:06:29 +00:00
}
} else {
ast_log ( LOG_WARNING , " Error creating writestream '%s', format '%s' \n " , prependfile , sfmt [ x ] ) ;
}
2003-12-22 18:22:21 +00:00
#if 0
2003-12-19 18:06:29 +00:00
if ( outmsg > 1 ) {
2003-12-22 18:22:21 +00:00
# else
if ( outmsg ) {
# endif
2003-12-19 18:06:29 +00:00
struct ast_frame * fr ;
for ( x = 0 ; x < fmtcnt ; x + + ) {
snprintf ( comment , sizeof ( comment ) , " Opening the real file %s.%s \n " , recordfile , sfmt [ x ] ) ;
2003-12-22 18:22:21 +00:00
realfiles [ x ] = ast_readfile ( recordfile , sfmt [ x ] , comment , O_RDONLY , 0 , 0 ) ;
2003-12-19 18:06:29 +00:00
if ( ! others [ x ] | | ! realfiles [ x ] )
break ;
if ( totalsilence )
ast_stream_rewind ( others [ x ] , totalsilence - 200 ) ;
else
ast_stream_rewind ( others [ x ] , 200 ) ;
ast_truncstream ( others [ x ] ) ;
/* add the original file too */
while ( ( fr = ast_readframe ( realfiles [ x ] ) ) ) {
ast_writestream ( others [ x ] , fr ) ;
}
ast_closestream ( others [ x ] ) ;
ast_closestream ( realfiles [ x ] ) ;
ast_filerename ( prependfile , recordfile , sfmt [ x ] ) ;
#if 0
ast_verbose ( " Recording Format: sfmts=%s, prependfile %s, recordfile %s \n " , sfmt [ x ] , prependfile , recordfile ) ;
# endif
ast_filedelete ( prependfile , sfmt [ x ] ) ;
}
}
if ( rfmt ) {
if ( ast_set_read_format ( chan , rfmt ) ) {
ast_log ( LOG_WARNING , " Unable to restore format %s to channel '%s' \n " , ast_getformatname ( rfmt ) , chan - > name ) ;
}
}
if ( outmsg ) {
if ( outmsg > 1 ) {
/* Let them know it worked */
ast_streamfile ( chan , " vm-msgsaved " , chan - > language ) ;
ast_waitstream ( chan , " " ) ;
}
}
return res ;
}
2003-11-13 01:47:23 +00:00
static int play_and_record ( struct ast_channel * chan , char * playfile , char * recordfile , int maxtime , char * fmt )
{
char d , * fmts ;
1999-11-21 21:15:14 +00:00
char comment [ 256 ] ;
2003-11-13 01:47:23 +00:00
int x , fmtcnt = 1 , res = - 1 , outmsg = 0 ;
struct ast_frame * f ;
struct ast_filestream * others [ MAX_OTHER_FORMATS ] ;
1999-11-21 21:15:14 +00:00
char * sfmt [ MAX_OTHER_FORMATS ] ;
2003-11-13 01:47:23 +00:00
char * stringp = NULL ;
time_t start , end ;
struct ast_dsp * sildet ; /* silence detector dsp */
int totalsilence = 0 ;
int dspsilence = 0 ;
int gotsilence = 0 ; /* did we timeout for silence? */
int rfmt = 0 ;
ast_log ( LOG_DEBUG , " play_and_record: %s, %s, '%s' \n " , playfile ? playfile : " <None> " , recordfile , fmt ) ;
snprintf ( comment , sizeof ( comment ) , " Playing %s, Recording to: %s on %s \n " , playfile ? playfile : " <None> " , recordfile , chan - > name ) ;
if ( playfile ) {
d = play_and_wait ( chan , playfile ) ;
2003-11-13 05:46:01 +00:00
if ( d > - 1 )
2003-11-13 01:47:23 +00:00
d = ast_streamfile ( chan , " beep " , chan - > language ) ;
if ( ! d )
d = ast_waitstream ( chan , " " ) ;
if ( d < 0 )
return - 1 ;
}
fmts = ast_strdupa ( fmt ) ;
stringp = fmts ;
strsep ( & stringp , " | " ) ;
ast_log ( LOG_DEBUG , " Recording Formats: sfmts=%s \n " , fmts ) ;
sfmt [ 0 ] = ast_strdupa ( fmts ) ;
while ( ( fmt = strsep ( & stringp , " | " ) ) ) {
if ( fmtcnt > MAX_OTHER_FORMATS - 1 ) {
ast_log ( LOG_WARNING , " Please increase MAX_OTHER_FORMATS in app_voicemail.c \n " ) ;
break ;
}
sfmt [ fmtcnt + + ] = ast_strdupa ( fmt ) ;
}
if ( maxtime )
time ( & start ) ;
for ( x = 0 ; x < fmtcnt ; x + + ) {
others [ x ] = ast_writefile ( recordfile , sfmt [ x ] , comment , O_TRUNC , 0 , 0700 ) ;
ast_verbose ( VERBOSE_PREFIX_3 " x=%i, open writing: %s format: %s, %p \n " , x , recordfile , sfmt [ x ] , others [ x ] ) ;
if ( ! others [ x ] ) {
break ;
}
}
sildet = ast_dsp_new ( ) ; //Create the silence detector
if ( ! sildet ) {
ast_log ( LOG_WARNING , " Unable to create silence detector :( \n " ) ;
return - 1 ;
}
ast_dsp_set_threshold ( sildet , silencethreshold ) ;
if ( maxsilence > 0 ) {
rfmt = chan - > readformat ;
res = ast_set_read_format ( chan , AST_FORMAT_SLINEAR ) ;
if ( res < 0 ) {
ast_log ( LOG_WARNING , " Unable to set to linear mode, giving up \n " ) ;
return - 1 ;
}
}
if ( x = = fmtcnt ) {
/* Loop forever, writing the packets we read to the writer(s), until
we read a # or get a hangup */
f = NULL ;
for ( ; ; ) {
res = ast_waitfor ( chan , 2000 ) ;
if ( ! res ) {
ast_log ( LOG_DEBUG , " One waitfor failed, trying another \n " ) ;
/* Try one more time in case of masq */
res = ast_waitfor ( chan , 2000 ) ;
if ( ! res ) {
ast_log ( LOG_WARNING , " No audio available on %s?? \n " , chan - > name ) ;
res = - 1 ;
}
}
if ( res < 0 ) {
f = NULL ;
break ;
}
f = ast_read ( chan ) ;
if ( ! f )
break ;
if ( f - > frametype = = AST_FRAME_VOICE ) {
/* write each format */
for ( x = 0 ; x < fmtcnt ; x + + ) {
res = ast_writestream ( others [ x ] , f ) ;
}
/* Silence Detection */
if ( maxsilence > 0 ) {
dspsilence = 0 ;
ast_dsp_silence ( sildet , f , & dspsilence ) ;
if ( dspsilence )
totalsilence = dspsilence ;
else
totalsilence = 0 ;
if ( totalsilence > maxsilence ) {
/* Ended happily with silence */
ast_frfree ( f ) ;
gotsilence = 1 ;
outmsg = 2 ;
break ;
}
}
/* Exit on any error */
if ( res ) {
ast_log ( LOG_WARNING , " Error writing frame \n " ) ;
ast_frfree ( f ) ;
break ;
}
} else if ( f - > frametype = = AST_FRAME_VIDEO ) {
/* Write only once */
ast_writestream ( others [ 0 ] , f ) ;
} else if ( f - > frametype = = AST_FRAME_DTMF ) {
if ( f - > subclass = = ' # ' ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " User ended message by pressing %c \n " , f - > subclass ) ;
res = ' # ' ;
outmsg = 2 ;
ast_frfree ( f ) ;
break ;
}
}
if ( maxtime ) {
time ( & end ) ;
if ( maxtime < ( end - start ) ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Took too long, cutting it short... \n " ) ;
res = ' t ' ;
ast_frfree ( f ) ;
break ;
}
}
ast_frfree ( f ) ;
}
if ( ! f ) {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " User hung up \n " ) ;
res = - 1 ;
outmsg = 1 ;
}
} else {
ast_log ( LOG_WARNING , " Error creating writestream '%s', format '%s' \n " , recordfile , sfmt [ x ] ) ;
}
for ( x = 0 ; x < fmtcnt ; x + + ) {
if ( ! others [ x ] )
break ;
if ( totalsilence )
ast_stream_rewind ( others [ x ] , totalsilence - 200 ) ;
else
ast_stream_rewind ( others [ x ] , 200 ) ;
ast_truncstream ( others [ x ] ) ;
ast_closestream ( others [ x ] ) ;
}
if ( rfmt ) {
if ( ast_set_read_format ( chan , rfmt ) ) {
ast_log ( LOG_WARNING , " Unable to restore format %s to channel '%s' \n " , ast_getformatname ( rfmt ) , chan - > name ) ;
}
}
if ( outmsg ) {
if ( outmsg > 1 ) {
/* Let them know it worked */
ast_streamfile ( chan , " vm-msgsaved " , chan - > language ) ;
ast_waitstream ( chan , " " ) ;
}
}
return res ;
}
static void free_user ( struct ast_vm_user * vmu )
{
if ( vmu - > alloced )
free ( vmu ) ;
}
static void free_zone ( struct vm_zone * z )
{
free ( z ) ;
}
static int leave_voicemail ( struct ast_channel * chan , char * ext , int silent , int busy , int unavail )
{
char comment [ 256 ] ;
2001-05-08 16:21:08 +00:00
char txtfile [ 256 ] ;
FILE * txt ;
2003-11-13 01:47:23 +00:00
int res = 0 ;
1999-11-21 21:15:14 +00:00
int msgnum ;
2001-05-08 16:21:08 +00:00
char date [ 256 ] ;
2001-08-05 21:46:13 +00:00
char dir [ 256 ] ;
char fn [ 256 ] ;
2001-12-27 11:07:33 +00:00
char prefile [ 256 ] = " " ;
2003-11-13 01:47:23 +00:00
char fmt [ 80 ] ;
char * context ;
2003-01-30 15:03:20 +00:00
char * ecodes = " # " ;
2003-11-13 01:47:23 +00:00
char * stringp ;
2002-06-28 15:21:23 +00:00
time_t start ;
time_t end ;
2003-11-13 01:47:23 +00:00
char tmp [ 256 ] = " " ;
struct ast_vm_user * vmu ;
struct ast_vm_user svm ;
strncpy ( tmp , ext , sizeof ( tmp ) - 1 ) ;
ext = tmp ;
context = strchr ( tmp , ' @ ' ) ;
if ( context ) {
* context = ' \0 ' ;
context + + ;
2003-01-30 15:03:20 +00:00
}
2003-11-13 01:47:23 +00:00
if ( ( vmu = find_user ( & svm , context , ext ) ) ) {
2001-12-27 11:07:33 +00:00
/* Setup pre-file if appropriate */
if ( busy )
2003-11-13 01:47:23 +00:00
snprintf ( prefile , sizeof ( prefile ) , " voicemail/%s/%s/busy " , vmu - > context , ext ) ;
2001-12-27 11:07:33 +00:00
else if ( unavail )
2003-11-13 01:47:23 +00:00
snprintf ( prefile , sizeof ( prefile ) , " voicemail/%s/%s/unavail " , vmu - > context , ext ) ;
make_dir ( dir , sizeof ( dir ) , vmu - > context , " " , " " ) ;
/* It's easier just to try to make it than to check for its existence */
if ( mkdir ( dir , 0700 ) & & ( errno ! = EEXIST ) )
ast_log ( LOG_WARNING , " mkdir '%s' failed: %s \n " , dir , strerror ( errno ) ) ;
make_dir ( dir , sizeof ( dir ) , vmu - > context , ext , " " ) ;
1999-11-21 21:15:14 +00:00
/* It's easier just to try to make it than to check for its existence */
if ( mkdir ( dir , 0700 ) & & ( errno ! = EEXIST ) )
ast_log ( LOG_WARNING , " mkdir '%s' failed: %s \n " , dir , strerror ( errno ) ) ;
2003-11-13 01:47:23 +00:00
make_dir ( dir , sizeof ( dir ) , vmu - > context , ext , " INBOX " ) ;
1999-11-21 21:15:14 +00:00
if ( mkdir ( dir , 0700 ) & & ( errno ! = EEXIST ) )
ast_log ( LOG_WARNING , " mkdir '%s' failed: %s \n " , dir , strerror ( errno ) ) ;
2003-04-09 23:56:15 +00:00
if ( ast_exists_extension ( chan , strlen ( chan - > macrocontext ) ? chan - > macrocontext : chan - > context , " o " , 1 , chan - > callerid ) )
2003-01-30 15:03:20 +00:00
ecodes = " #0 " ;
2001-12-27 11:07:33 +00:00
/* Play the beginning intro if desired */
if ( strlen ( prefile ) ) {
2002-03-01 16:54:59 +00:00
if ( ast_fileexists ( prefile , NULL , NULL ) > 0 ) {
2001-12-27 11:07:33 +00:00
if ( ast_streamfile ( chan , prefile , chan - > language ) > - 1 )
2003-11-13 01:47:23 +00:00
res = ast_waitstream ( chan , " #0 " ) ;
2001-12-27 11:07:33 +00:00
} else {
ast_log ( LOG_DEBUG , " %s doesn't exist, doing what we can \n " , prefile ) ;
2003-11-13 01:47:23 +00:00
res = invent_message ( chan , vmu - > context , ext , busy , ecodes ) ;
2001-12-27 11:07:33 +00:00
}
2003-11-13 01:47:23 +00:00
if ( res < 0 ) {
2001-12-27 11:07:33 +00:00
ast_log ( LOG_DEBUG , " Hang up during prefile playback \n " ) ;
2003-11-13 01:47:23 +00:00
free_user ( vmu ) ;
2001-12-27 11:07:33 +00:00
return - 1 ;
}
}
2003-11-13 01:47:23 +00:00
if ( res = = ' # ' ) {
/* On a '#' we skip the instructions */
silent = 1 ;
res = 0 ;
}
if ( ! res & & ! silent ) {
res = ast_streamfile ( chan , INTRO , chan - > language ) ;
if ( ! res )
res = ast_waitstream ( chan , ecodes ) ;
if ( res = = ' # ' ) {
2001-12-27 11:07:33 +00:00
silent = 1 ;
2003-11-13 01:47:23 +00:00
res = 0 ;
2002-06-28 15:21:23 +00:00
}
2003-11-13 01:47:23 +00:00
}
/* Check for a '0' here */
if ( res = = ' 0 ' ) {
2003-04-09 23:26:26 +00:00
strncpy ( chan - > exten , " o " , sizeof ( chan - > exten ) - 1 ) ;
2003-04-09 23:56:15 +00:00
if ( strlen ( chan - > macrocontext ) )
strncpy ( chan - > context , chan - > macrocontext , sizeof ( chan - > context ) - 1 ) ;
2003-01-30 15:03:20 +00:00
chan - > priority = 0 ;
2003-11-13 01:47:23 +00:00
free_user ( vmu ) ;
2003-01-30 15:03:20 +00:00
return 0 ;
2001-12-27 11:07:33 +00:00
}
2003-11-13 01:47:23 +00:00
if ( res > = 0 ) {
/* Unless we're *really* silent, try to send the beep */
res = ast_streamfile ( chan , " beep " , chan - > language ) ;
if ( ! res )
res = ast_waitstream ( chan , " " ) ;
}
if ( res < 0 ) {
free_user ( vmu ) ;
return - 1 ;
}
/* The meat of recording the message... All the announcements and beeps have been played*/
strncpy ( fmt , vmfmts , sizeof ( fmt ) - 1 ) ;
if ( strlen ( fmt ) ) {
msgnum = 0 ;
do {
make_file ( fn , sizeof ( fn ) , dir , msgnum ) ;
snprintf ( comment , sizeof ( comment ) , " Voicemail from %s to %s (%s) on %s \n " ,
( chan - > callerid ? chan - > callerid : " Unknown " ) ,
vmu - > fullname , ext , chan - > name ) ;
if ( ast_fileexists ( fn , NULL , chan - > language ) < = 0 )
break ;
msgnum + + ;
} while ( msgnum < MAXMSG ) ;
if ( msgnum < MAXMSG ) {
/* Store information */
snprintf ( txtfile , sizeof ( txtfile ) , " %s.txt " , fn ) ;
txt = fopen ( txtfile , " w+ " ) ;
if ( txt ) {
get_date ( date , sizeof ( date ) ) ;
time ( & start ) ;
fprintf ( txt ,
2003-03-05 06:00:17 +00:00
" ; \n "
" ; Message Information file \n "
" ; \n "
" [message] \n "
2001-05-08 16:21:08 +00:00
" origmailbox=%s \n "
" context=%s \n "
" exten=%s \n "
" priority=%d \n "
" callerchan=%s \n "
" callerid=%s \n "
2002-07-31 20:34:22 +00:00
" origdate=%s \n "
" origtime=%ld \n " ,
2001-05-08 16:21:08 +00:00
ext ,
chan - > context ,
chan - > exten ,
chan - > priority ,
chan - > name ,
chan - > callerid ? chan - > callerid : " Unknown " ,
2003-11-13 01:47:23 +00:00
date , ( long ) time ( NULL ) ) ;
fclose ( txt ) ;
} else
ast_log ( LOG_WARNING , " Error opening text file for output \n " ) ;
res = play_and_record ( chan , NULL , fn , vmmaxmessage , fmt ) ;
if ( res > 0 )
res = 0 ;
txt = fopen ( txtfile , " a " ) ;
if ( txt ) {
time ( & end ) ;
fprintf ( txt , " duration=%ld \n " , ( long ) ( end - start ) ) ;
fclose ( txt ) ;
}
stringp = fmt ;
strsep ( & stringp , " | " ) ;
/* Send e-mail if applicable */
if ( strlen ( vmu - > email ) ) {
int attach_user_voicemail = attach_voicemail ;
char * myserveremail = serveremail ;
if ( vmu - > attach > - 1 )
attach_user_voicemail = vmu - > attach ;
if ( strlen ( vmu - > serveremail ) )
myserveremail = vmu - > serveremail ;
sendmail ( myserveremail , vmu , msgnum , ext , chan - > callerid , fn , fmt , end - start , attach_user_voicemail ) ;
}
if ( strlen ( vmu - > pager ) ) {
char * myserveremail = serveremail ;
if ( strlen ( vmu - > serveremail ) )
myserveremail = vmu - > serveremail ;
sendpage ( myserveremail , vmu - > pager , msgnum , ext , chan - > callerid , end - start , vmu ) ;
}
} else
ast_log ( LOG_WARNING , " No more messages possible \n " ) ;
1999-11-21 21:15:14 +00:00
} else
2003-11-13 01:47:23 +00:00
ast_log ( LOG_WARNING , " No format for saving voicemail? \n " ) ;
free_user ( vmu ) ;
2003-11-14 00:21:31 +00:00
} else {
1999-11-21 21:15:14 +00:00
ast_log ( LOG_WARNING , " No entry in voicemail config file for '%s' \n " , ext ) ;
2003-11-14 00:21:31 +00:00
/*Send the call to n+101 priority, where n is the current priority*/
if ( ast_exists_extension ( chan , chan - > context , chan - > exten , chan - > priority + 101 , chan - > callerid ) )
chan - > priority + = 100 ;
}
1999-11-21 21:15:14 +00:00
/* Leave voicemail for someone */
2003-02-24 06:00:18 +00:00
manager_event ( EVENT_FLAG_CALL , " MessageWaiting " , " Mailbox: %s \r \n Waiting: %d \r \n " , ext , ast_app_has_voicemail ( ext ) ) ;
1999-11-21 21:15:14 +00:00
return res ;
}
2001-08-05 21:46:13 +00:00
static char * mbox ( int id )
{
switch ( id ) {
case 0 :
return " INBOX " ;
case 1 :
return " Old " ;
case 2 :
return " Work " ;
case 3 :
return " Family " ;
case 4 :
return " Friends " ;
case 5 :
return " Cust1 " ;
case 6 :
return " Cust2 " ;
case 7 :
return " Cust3 " ;
case 8 :
return " Cust4 " ;
case 9 :
return " Cust5 " ;
default :
return " Unknown " ;
}
}
static int count_messages ( char * dir )
{
int x ;
char fn [ 256 ] ;
for ( x = 0 ; x < MAXMSG ; x + + ) {
make_file ( fn , sizeof ( fn ) , dir , x ) ;
if ( ast_fileexists ( fn , NULL , NULL ) < 1 )
break ;
}
return x ;
}
static int say_and_wait ( struct ast_channel * chan , int num )
{
int d ;
2001-12-27 11:07:33 +00:00
d = ast_say_number ( chan , num , AST_DIGIT_ANY , chan - > language ) ;
2001-08-05 21:46:13 +00:00
return d ;
}
static int copy ( char * infile , char * outfile )
{
int ifd ;
int ofd ;
int res ;
int len ;
char buf [ 4096 ] ;
if ( ( ifd = open ( infile , O_RDONLY ) ) < 0 ) {
ast_log ( LOG_WARNING , " Unable to open %s in read-only mode \n " , infile ) ;
return - 1 ;
}
if ( ( ofd = open ( outfile , O_WRONLY | O_TRUNC | O_CREAT , 0600 ) ) < 0 ) {
ast_log ( LOG_WARNING , " Unable to open %s in write-only mode \n " , outfile ) ;
close ( ifd ) ;
return - 1 ;
}
do {
len = read ( ifd , buf , sizeof ( buf ) ) ;
if ( len < 0 ) {
ast_log ( LOG_WARNING , " Read failed on %s: %s \n " , infile , strerror ( errno ) ) ;
close ( ifd ) ;
close ( ofd ) ;
unlink ( outfile ) ;
}
if ( len ) {
res = write ( ofd , buf , len ) ;
if ( res ! = len ) {
ast_log ( LOG_WARNING , " Write failed on %s (%d of %d): %s \n " , outfile , res , len , strerror ( errno ) ) ;
close ( ifd ) ;
close ( ofd ) ;
unlink ( outfile ) ;
}
}
} while ( len ) ;
close ( ifd ) ;
close ( ofd ) ;
return 0 ;
}
2003-11-13 01:47:23 +00:00
static int save_to_folder ( char * dir , int msg , char * context , char * username , int box )
2001-08-05 21:46:13 +00:00
{
char sfn [ 256 ] ;
char dfn [ 256 ] ;
char ddir [ 256 ] ;
char txt [ 256 ] ;
char ntxt [ 256 ] ;
char * dbox = mbox ( box ) ;
int x ;
make_file ( sfn , sizeof ( sfn ) , dir , msg ) ;
2003-11-13 01:47:23 +00:00
make_dir ( ddir , sizeof ( ddir ) , context , username , dbox ) ;
2001-08-05 21:46:13 +00:00
mkdir ( ddir , 0700 ) ;
for ( x = 0 ; x < MAXMSG ; x + + ) {
make_file ( dfn , sizeof ( dfn ) , ddir , x ) ;
if ( ast_fileexists ( dfn , NULL , NULL ) < 0 )
break ;
}
if ( x > = MAXMSG )
return - 1 ;
ast_filecopy ( sfn , dfn , NULL ) ;
if ( strcmp ( sfn , dfn ) ) {
snprintf ( txt , sizeof ( txt ) , " %s.txt " , sfn ) ;
snprintf ( ntxt , sizeof ( ntxt ) , " %s.txt " , dfn ) ;
copy ( txt , ntxt ) ;
}
return 0 ;
}
2001-12-27 11:07:33 +00:00
static int adsi_logo ( unsigned char * buf )
{
int bytes = 0 ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 1 , ADSI_JUST_CENT , 0 , " Comedian Mail " , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 2 , ADSI_JUST_CENT , 0 , " (C)2002 LSS, Inc. " , " " ) ;
return bytes ;
}
static int adsi_load_vmail ( struct ast_channel * chan , int * useadsi )
{
char buf [ 256 ] ;
int bytes = 0 ;
int x ;
char num [ 5 ] ;
* useadsi = 0 ;
bytes + = adsi_data_mode ( buf + bytes ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
bytes = 0 ;
bytes + = adsi_logo ( buf ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_CENT , 0 , " Downloading Scripts " , " " ) ;
# ifdef DISPLAY
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_LEFT , 0 , " . " , " " ) ;
# endif
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_data_mode ( buf + bytes ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
if ( adsi_begin_download ( chan , addesc , adapp , adsec , adver ) ) {
bytes = 0 ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_CENT , 0 , " Load Cancelled. " , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_CENT , 0 , " ADSI Unavailable " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
return 0 ;
}
# ifdef DISPLAY
/* Add a dot */
bytes = 0 ;
bytes + = adsi_logo ( buf ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_CENT , 0 , " Downloading Scripts " , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_LEFT , 0 , " .. " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
# endif
bytes = 0 ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 0 , " Listen " , " Listen " , " 1 " , 1 ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 1 , " Folder " , " Folder " , " 2 " , 1 ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 2 , " Advanced " , " Advnced " , " 3 " , 1 ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 3 , " Options " , " Options " , " 0 " , 1 ) ;
2001-12-27 11:07:33 +00:00
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 4 , " Help " , " Help " , " * " , 1 ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 5 , " Exit " , " Exit " , " # " , 1 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DOWNLOAD ) ;
# ifdef DISPLAY
/* Add another dot */
bytes = 0 ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_LEFT , 0 , " ... " , " " ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
# endif
bytes = 0 ;
/* These buttons we load but don't use yet */
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 6 , " Previous " , " Prev " , " 4 " , 1 ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 8 , " Repeat " , " Repeat " , " 5 " , 1 ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 7 , " Delete " , " Delete " , " 7 " , 1 ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 9 , " Next " , " Next " , " 6 " , 1 ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 10 , " Save " , " Save " , " 9 " , 1 ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 11 , " Undelete " , " Restore " , " 7 " , 1 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DOWNLOAD ) ;
# ifdef DISPLAY
/* Add another dot */
bytes = 0 ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_LEFT , 0 , " .... " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
# endif
bytes = 0 ;
for ( x = 0 ; x < 5 ; x + + ) {
snprintf ( num , sizeof ( num ) , " %d " , x ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 12 + x , mbox ( x ) , mbox ( x ) , num , 1 ) ;
}
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 12 + 5 , " Cancel " , " Cancel " , " # " , 1 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DOWNLOAD ) ;
# ifdef DISPLAY
/* Add another dot */
bytes = 0 ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_LEFT , 0 , " ..... " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
# endif
if ( adsi_end_download ( chan ) ) {
bytes = 0 ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_CENT , 0 , " Download Unsuccessful. " , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_CENT , 0 , " ADSI Unavailable " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
return 0 ;
}
bytes = 0 ;
bytes + = adsi_download_disconnect ( buf + bytes ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DOWNLOAD ) ;
ast_log ( LOG_DEBUG , " Done downloading scripts... \n " ) ;
# ifdef DISPLAY
/* Add last dot */
bytes = 0 ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_CENT , 0 , " ...... " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
# endif
ast_log ( LOG_DEBUG , " Restarting session... \n " ) ;
bytes = 0 ;
/* Load the session now */
if ( adsi_load_session ( chan , adapp , adver , 1 ) = = 1 ) {
* useadsi = 1 ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_CENT , 0 , " Scripts Loaded! " , " " ) ;
} else
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_CENT , 0 , " Load Failed! " , " " ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
return 0 ;
}
static void adsi_begin ( struct ast_channel * chan , int * useadsi )
{
int x ;
2003-03-06 06:00:17 +00:00
if ( ! adsi_available ( chan ) )
2003-03-05 06:00:17 +00:00
return ;
2001-12-27 11:07:33 +00:00
x = adsi_load_session ( chan , adapp , adver , 1 ) ;
if ( x < 0 )
return ;
if ( ! x ) {
if ( adsi_load_vmail ( chan , useadsi ) ) {
ast_log ( LOG_WARNING , " Unable to upload voicemail scripts \n " ) ;
return ;
}
} else
* useadsi = 1 ;
}
static void adsi_login ( struct ast_channel * chan )
{
char buf [ 256 ] ;
int bytes = 0 ;
2002-06-28 15:21:23 +00:00
unsigned char keys [ 8 ] ;
2001-12-27 11:07:33 +00:00
int x ;
if ( ! adsi_available ( chan ) )
return ;
2002-06-28 15:21:23 +00:00
for ( x = 0 ; x < 8 ; x + + )
2001-12-27 11:07:33 +00:00
keys [ x ] = 0 ;
/* Set one key for next */
keys [ 3 ] = ADSI_KEY_APPS + 3 ;
bytes + = adsi_logo ( buf + bytes ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_CENT , 0 , " " , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_CENT , 0 , " " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_input_format ( buf + bytes , 1 , ADSI_DIR_FROM_LEFT , 0 , " Mailbox: ****** " , " " ) ;
bytes + = adsi_input_control ( buf + bytes , ADSI_COMM_PAGE , 4 , 1 , 1 , ADSI_JUST_LEFT ) ;
bytes + = adsi_load_soft_key ( buf + bytes , ADSI_KEY_APPS + 3 , " Enter " , " Enter " , " # " , 1 ) ;
bytes + = adsi_set_keys ( buf + bytes , keys ) ;
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
static void adsi_password ( struct ast_channel * chan )
{
char buf [ 256 ] ;
int bytes = 0 ;
2002-06-28 15:21:23 +00:00
unsigned char keys [ 8 ] ;
2001-12-27 11:07:33 +00:00
int x ;
if ( ! adsi_available ( chan ) )
return ;
2002-06-28 15:21:23 +00:00
for ( x = 0 ; x < 8 ; x + + )
2001-12-27 11:07:33 +00:00
keys [ x ] = 0 ;
/* Set one key for next */
keys [ 3 ] = ADSI_KEY_APPS + 3 ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_input_format ( buf + bytes , 1 , ADSI_DIR_FROM_LEFT , 0 , " Password: ****** " , " " ) ;
bytes + = adsi_input_control ( buf + bytes , ADSI_COMM_PAGE , 4 , 0 , 1 , ADSI_JUST_LEFT ) ;
bytes + = adsi_set_keys ( buf + bytes , keys ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
static void adsi_folders ( struct ast_channel * chan , int start , char * label )
{
char buf [ 256 ] ;
int bytes = 0 ;
2002-06-28 15:21:23 +00:00
unsigned char keys [ 8 ] ;
2001-12-27 11:07:33 +00:00
int x , y ;
if ( ! adsi_available ( chan ) )
return ;
for ( x = 0 ; x < 5 ; x + + ) {
y = ADSI_KEY_APPS + 12 + start + x ;
if ( y > ADSI_KEY_APPS + 12 + 4 )
y = 0 ;
keys [ x ] = ADSI_KEY_SKT | y ;
}
keys [ 5 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 17 ) ;
2002-06-28 15:21:23 +00:00
keys [ 6 ] = 0 ;
keys [ 7 ] = 0 ;
2001-12-27 11:07:33 +00:00
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 1 , ADSI_JUST_CENT , 0 , label , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 2 , ADSI_JUST_CENT , 0 , " " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_set_keys ( buf + bytes , keys ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
static void adsi_message ( struct ast_channel * chan , char * folder , int msg , int last , int deleted , char * fn )
{
int bytes = 0 ;
char buf [ 256 ] , buf1 [ 256 ] , buf2 [ 256 ] ;
char fn2 [ 256 ] ;
2003-11-13 01:47:23 +00:00
2001-12-27 11:07:33 +00:00
char cid [ 256 ] = " " ;
char * val ;
char * name , * num ;
char datetime [ 21 ] = " " ;
FILE * f ;
2002-06-28 15:21:23 +00:00
unsigned char keys [ 8 ] ;
2001-12-27 11:07:33 +00:00
int x ;
if ( ! adsi_available ( chan ) )
return ;
/* Retrieve important info */
snprintf ( fn2 , sizeof ( fn2 ) , " %s.txt " , fn ) ;
f = fopen ( fn2 , " r " ) ;
if ( f ) {
while ( ! feof ( f ) ) {
fgets ( buf , sizeof ( buf ) , f ) ;
if ( ! feof ( f ) ) {
2003-01-30 15:03:20 +00:00
char * stringp = NULL ;
stringp = buf ;
strsep ( & stringp , " = " ) ;
val = strsep ( & stringp , " = " ) ;
2001-12-27 11:07:33 +00:00
if ( val & & strlen ( val ) ) {
if ( ! strcmp ( buf , " callerid " ) )
strncpy ( cid , val , sizeof ( cid ) - 1 ) ;
if ( ! strcmp ( buf , " origdate " ) )
strncpy ( datetime , val , sizeof ( datetime ) - 1 ) ;
}
}
}
fclose ( f ) ;
}
/* New meaning for keys */
for ( x = 0 ; x < 5 ; x + + )
keys [ x ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 6 + x ) ;
2002-06-28 15:21:23 +00:00
keys [ 6 ] = 0x0 ;
keys [ 7 ] = 0x0 ;
2001-12-27 11:07:33 +00:00
if ( ! msg ) {
/* No prev key, provide "Folder" instead */
keys [ 0 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 1 ) ;
}
if ( msg > = last ) {
/* If last message ... */
if ( msg ) {
/* but not only message, provide "Folder" instead */
keys [ 3 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 1 ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
} else {
/* Otherwise if only message, leave blank */
keys [ 3 ] = 1 ;
}
}
if ( strlen ( cid ) ) {
ast_callerid_parse ( cid , & name , & num ) ;
if ( ! name )
name = num ;
} else
name = " Unknown Caller " ;
/* If deleted, show "undeleted" */
2003-11-13 01:47:23 +00:00
2001-12-27 11:07:33 +00:00
if ( deleted )
keys [ 1 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 11 ) ;
/* Except "Exit" */
keys [ 5 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 5 ) ;
snprintf ( buf1 , sizeof ( buf1 ) , " %s%s " , folder ,
strcasecmp ( folder , " INBOX " ) ? " Messages " : " " ) ;
snprintf ( buf2 , sizeof ( buf2 ) , " Message %d of %d " , msg + 1 , last + 1 ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 1 , ADSI_JUST_LEFT , 0 , buf1 , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 2 , ADSI_JUST_LEFT , 0 , buf2 , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_LEFT , 0 , name , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_LEFT , 0 , datetime , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_set_keys ( buf + bytes , keys ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
static void adsi_delete ( struct ast_channel * chan , int msg , int last , int deleted )
{
int bytes = 0 ;
char buf [ 256 ] ;
2002-06-28 15:21:23 +00:00
unsigned char keys [ 8 ] ;
2001-12-27 11:07:33 +00:00
int x ;
if ( ! adsi_available ( chan ) )
return ;
/* New meaning for keys */
for ( x = 0 ; x < 5 ; x + + )
keys [ x ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 6 + x ) ;
2002-06-28 15:21:23 +00:00
keys [ 6 ] = 0x0 ;
keys [ 7 ] = 0x0 ;
2001-12-27 11:07:33 +00:00
if ( ! msg ) {
/* No prev key, provide "Folder" instead */
keys [ 0 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 1 ) ;
}
if ( msg > = last ) {
/* If last message ... */
if ( msg ) {
/* but not only message, provide "Folder" instead */
keys [ 3 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 1 ) ;
} else {
/* Otherwise if only message, leave blank */
keys [ 3 ] = 1 ;
}
}
/* If deleted, show "undeleted" */
if ( deleted )
keys [ 1 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 11 ) ;
/* Except "Exit" */
keys [ 5 ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + 5 ) ;
bytes + = adsi_set_keys ( buf + bytes , keys ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
static void adsi_status ( struct ast_channel * chan , int new , int old , int lastmsg )
{
char buf [ 256 ] , buf1 [ 256 ] , buf2 [ 256 ] ;
int bytes = 0 ;
2002-06-28 15:21:23 +00:00
unsigned char keys [ 8 ] ;
2001-12-27 11:07:33 +00:00
int x ;
char * newm = ( new = = 1 ) ? " message " : " messages " ;
char * oldm = ( old = = 1 ) ? " message " : " messages " ;
if ( ! adsi_available ( chan ) )
return ;
if ( new ) {
snprintf ( buf1 , sizeof ( buf1 ) , " You have %d new " , new ) ;
if ( old ) {
strcat ( buf1 , " and " ) ;
snprintf ( buf2 , sizeof ( buf2 ) , " %d old %s. " , old , oldm ) ;
} else {
snprintf ( buf2 , sizeof ( buf2 ) , " %s. " , newm ) ;
}
} else if ( old ) {
snprintf ( buf1 , sizeof ( buf1 ) , " You have %d old " , old ) ;
snprintf ( buf2 , sizeof ( buf2 ) , " %s. " , oldm ) ;
} else {
strcpy ( buf1 , " You have no messages. " ) ;
strcpy ( buf2 , " " ) ;
}
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 1 , ADSI_JUST_LEFT , 0 , buf1 , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 2 , ADSI_JUST_LEFT , 0 , buf2 , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
for ( x = 0 ; x < 6 ; x + + )
keys [ x ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + x ) ;
2002-06-28 15:21:23 +00:00
keys [ 6 ] = 0 ;
keys [ 7 ] = 0 ;
2001-12-27 11:07:33 +00:00
/* Don't let them listen if there are none */
if ( lastmsg < 0 )
keys [ 0 ] = 1 ;
bytes + = adsi_set_keys ( buf + bytes , keys ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
static void adsi_status2 ( struct ast_channel * chan , char * folder , int messages )
{
char buf [ 256 ] , buf1 [ 256 ] , buf2 [ 256 ] ;
int bytes = 0 ;
2002-06-28 15:21:23 +00:00
unsigned char keys [ 8 ] ;
2001-12-27 11:07:33 +00:00
int x ;
char * mess = ( messages = = 1 ) ? " message " : " messages " ;
if ( ! adsi_available ( chan ) )
return ;
/* Original command keys */
for ( x = 0 ; x < 6 ; x + + )
keys [ x ] = ADSI_KEY_SKT | ( ADSI_KEY_APPS + x ) ;
2002-06-28 15:21:23 +00:00
keys [ 6 ] = 0 ;
keys [ 7 ] = 0 ;
2001-12-27 11:07:33 +00:00
if ( messages < 1 )
keys [ 0 ] = 0 ;
snprintf ( buf1 , sizeof ( buf1 ) , " %s%s has " , folder ,
strcasecmp ( folder , " INBOX " ) ? " folder " : " " ) ;
if ( messages )
snprintf ( buf2 , sizeof ( buf2 ) , " %d %s. " , messages , mess ) ;
else
strcpy ( buf2 , " no messages. " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 1 , ADSI_JUST_LEFT , 0 , buf1 , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 2 , ADSI_JUST_LEFT , 0 , buf2 , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_LEFT , 0 , " " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_set_keys ( buf + bytes , keys ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
static void adsi_clear ( struct ast_channel * chan )
{
char buf [ 256 ] ;
int bytes = 0 ;
if ( ! adsi_available ( chan ) )
return ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
static void adsi_goodbye ( struct ast_channel * chan )
{
char buf [ 256 ] ;
int bytes = 0 ;
2003-03-06 06:00:17 +00:00
2001-12-27 11:07:33 +00:00
if ( ! adsi_available ( chan ) )
return ;
bytes + = adsi_logo ( buf + bytes ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_LEFT , 0 , " " , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_CENT , 0 , " Goodbye " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
2003-11-13 01:47:23 +00:00
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
2001-12-27 11:07:33 +00:00
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
2001-08-05 21:46:13 +00:00
static int get_folder ( struct ast_channel * chan , int start )
{
int x ;
int d ;
char fn [ 256 ] ;
d = play_and_wait ( chan , " vm-press " ) ;
if ( d )
return d ;
for ( x = start ; x < 5 ; x + + ) {
2001-12-27 11:07:33 +00:00
if ( ( d = ast_say_number ( chan , x , AST_DIGIT_ANY , chan - > language ) ) )
2001-08-05 21:46:13 +00:00
return d ;
d = play_and_wait ( chan , " vm-for " ) ;
if ( d )
return d ;
snprintf ( fn , sizeof ( fn ) , " vm-%s " , mbox ( x ) ) ;
d = play_and_wait ( chan , fn ) ;
if ( d )
return d ;
d = play_and_wait ( chan , " vm-messages " ) ;
if ( d )
return d ;
d = ast_waitfordigit ( chan , 500 ) ;
if ( d )
return d ;
}
d = play_and_wait ( chan , " vm-tocancel " ) ;
if ( d )
return d ;
d = ast_waitfordigit ( chan , 4000 ) ;
return d ;
}
2003-11-13 01:47:23 +00:00
static int get_folder2 ( struct ast_channel * chan , char * fn , int start )
{
int res = 0 ;
res = play_and_wait ( chan , fn ) ;
while ( ( ( res < ' 0 ' ) | | ( res > ' 9 ' ) ) & &
( res ! = ' # ' ) & & ( res > = 0 ) ) {
res = get_folder ( chan , 0 ) ;
}
return res ;
}
2003-12-19 18:06:29 +00:00
static int vm_forwardoptions ( struct ast_channel * chan , struct ast_vm_user * vmu , char * curdir , int curmsg , char * vmfts , char * context )
{
int cmd = 0 ;
int retries = 0 ;
while ( ( cmd > = 0 ) & & ( cmd ! = ' t ' ) & & ( cmd ! = ' # ' ) ) {
if ( cmd )
retries = 0 ;
switch ( cmd ) {
case ' 1 ' :
/* prepend a message to the current message and return */
{
char file [ 200 ] ;
snprintf ( file , sizeof ( file ) , " %s/msg%04d " , curdir , curmsg ) ;
cmd = play_and_prepend ( chan , NULL , file , 0 , vmfmts ) ;
break ;
}
case ' 2 ' :
cmd = ' t ' ;
break ;
case ' # ' :
cmd = ' # ' ;
break ;
default :
cmd = play_and_wait ( chan , " vm-forwardoptions " ) ;
if ( ! cmd )
cmd = ast_waitfordigit ( chan , 6000 ) ;
if ( ! cmd )
retries + + ;
if ( retries > 3 )
cmd = ' t ' ;
}
}
if ( cmd = = ' t ' )
cmd = 0 ;
return cmd ;
}
static int forward_message ( struct ast_channel * chan , char * context , char * dir , int curmsg , struct ast_vm_user * sender , char * fmt )
2002-03-01 16:54:59 +00:00
{
char username [ 70 ] ;
char sys [ 256 ] ;
char todir [ 256 ] ;
int todircount = 0 ;
2003-04-15 00:19:27 +00:00
long duration ;
2003-03-05 06:00:17 +00:00
struct ast_config * mif ;
char miffile [ 256 ] ;
char fn [ 256 ] ;
char callerid [ 512 ] ;
2003-12-19 18:06:29 +00:00
int res = 0 , cmd = 0 ;
2003-12-22 16:35:48 +00:00
struct ast_vm_user * receiver , * extensions = NULL , * vmtmp = NULL , * vmfree ;
2003-11-13 01:47:23 +00:00
char tmp [ 256 ] ;
char * stringp , * s ;
2003-12-19 18:06:29 +00:00
int saved_messages = 0 , found = 0 ;
int valid_extensions = 0 ;
while ( ! res & & ! valid_extensions ) {
2003-11-13 01:47:23 +00:00
res = ast_streamfile ( chan , " vm-extension " , chan - > language ) ;
if ( res )
break ;
if ( ( res = ast_readstring ( chan , username , sizeof ( username ) - 1 , 2000 , 10000 , " # " ) < 0 ) )
break ;
2003-12-19 18:06:29 +00:00
/* start all over if no username */
if ( ! strlen ( username ) )
continue ;
stringp = username ;
s = strsep ( & stringp , " * " ) ;
/* start optimistic */
valid_extensions = 1 ;
while ( s ) {
/* find_user is going to malloc since we have a NULL as first argument */
if ( ( receiver = find_user ( NULL , context , s ) ) ) {
if ( ! extensions )
vmtmp = extensions = receiver ;
else {
vmtmp - > next = receiver ;
vmtmp = receiver ;
}
found + + ;
} else {
valid_extensions = 0 ;
2002-03-01 16:54:59 +00:00
break ;
2003-11-13 01:47:23 +00:00
}
2003-12-19 18:06:29 +00:00
s = strsep ( & stringp , " * " ) ;
}
/* break from the loop of reading the extensions */
if ( valid_extensions )
break ;
/* invalid extension, try again */
res = play_and_wait ( chan , " pbx-invalid " ) ;
}
/* check if we're clear to proceed */
if ( ! extensions | | ! valid_extensions )
return res ;
vmtmp = extensions ;
cmd = vm_forwardoptions ( chan , sender , dir , curmsg , vmfmts , context ) ;
while ( ! res & & vmtmp ) {
/* if (play_and_wait(chan, "vm-savedto"))
break ;
*/
snprintf ( todir , sizeof ( todir ) , " %s/voicemail/%s/%s/INBOX " , ( char * ) ast_config_AST_SPOOL_DIR , vmtmp - > context , vmtmp - > mailbox ) ;
snprintf ( sys , sizeof ( sys ) , " mkdir -p %s \n " , todir ) ;
ast_log ( LOG_DEBUG , sys ) ;
system ( sys ) ;
todircount = count_messages ( todir ) ;
strncpy ( tmp , fmt , sizeof ( tmp ) ) ;
stringp = tmp ;
while ( ( s = strsep ( & stringp , " | " ) ) ) {
/* XXX This is a hack -- we should use build_filename or similar XXX */
if ( ! strcasecmp ( s , " wav49 " ) )
s = " WAV " ;
snprintf ( sys , sizeof ( sys ) , " cp %s/msg%04d.%s %s/msg%04d.%s \n " , dir , curmsg , s , todir , todircount , s ) ;
2003-11-13 01:47:23 +00:00
ast_log ( LOG_DEBUG , sys ) ;
2003-03-05 06:00:17 +00:00
system ( sys ) ;
2003-12-19 18:06:29 +00:00
}
snprintf ( sys , sizeof ( sys ) , " cp %s/msg%04d.txt %s/msg%04d.txt \n " , dir , curmsg , todir , todircount ) ;
ast_log ( LOG_DEBUG , sys ) ;
system ( sys ) ;
snprintf ( fn , sizeof ( fn ) , " %s/msg%04d " , todir , todircount ) ;
/* load the information on the source message so we can send an e-mail like a new message */
snprintf ( miffile , sizeof ( miffile ) , " %s/msg%04d.txt " , dir , curmsg ) ;
if ( ( mif = ast_load ( miffile ) ) ) {
/* set callerid and duration variables */
snprintf ( callerid , sizeof ( callerid ) , " FWD from: %s from %s " , sender - > fullname , ast_variable_retrieve ( mif , NULL , " callerid " ) ) ;
s = ast_variable_retrieve ( mif , NULL , " duration " ) ;
if ( s )
duration = atol ( s ) ;
else
duration = 0 ;
if ( strlen ( vmtmp - > email ) ) {
2003-11-13 01:47:23 +00:00
int attach_user_voicemail = attach_voicemail ;
char * myserveremail = serveremail ;
2003-12-19 18:06:29 +00:00
if ( vmtmp - > attach > - 1 )
attach_user_voicemail = vmtmp - > attach ;
if ( strlen ( vmtmp - > serveremail ) )
myserveremail = vmtmp - > serveremail ;
sendmail ( myserveremail , vmtmp , todircount , vmtmp - > mailbox , callerid , fn , tmp , duration , attach_user_voicemail ) ;
}
if ( strlen ( vmtmp - > pager ) ) {
2003-11-13 01:47:23 +00:00
char * myserveremail = serveremail ;
2003-12-19 18:06:29 +00:00
if ( strlen ( vmtmp - > serveremail ) )
myserveremail = vmtmp - > serveremail ;
sendpage ( myserveremail , vmtmp - > pager , todircount , vmtmp - > mailbox , callerid , duration , vmtmp ) ;
2003-11-13 01:47:23 +00:00
}
2003-03-05 06:00:17 +00:00
2003-12-19 18:06:29 +00:00
ast_destroy ( mif ) ; /* or here */
}
/* Leave voicemail for someone */
manager_event ( EVENT_FLAG_CALL , " MessageWaiting " , " Mailbox: %s \r \n Waiting: %d \r \n " , vmtmp - > mailbox , ast_app_has_voicemail ( vmtmp - > mailbox ) ) ;
2003-03-05 06:00:17 +00:00
2003-12-19 18:06:29 +00:00
saved_messages + + ;
2003-12-22 16:35:48 +00:00
vmfree = vmtmp ;
2003-12-19 18:06:29 +00:00
vmtmp = vmtmp - > next ;
2003-12-22 16:35:48 +00:00
free_user ( vmfree ) ;
2003-12-19 18:06:29 +00:00
}
if ( saved_messages > 0 ) {
/* give confirmatopm that the message was saved */
if ( saved_messages = = 1 )
2003-11-13 01:47:23 +00:00
res = play_and_wait ( chan , " vm-message " ) ;
2003-12-19 18:06:29 +00:00
else
res = play_and_wait ( chan , " vm-messages " ) ;
if ( ! res )
res = play_and_wait ( chan , " vm-saved " ) ;
2002-03-01 16:54:59 +00:00
}
2003-12-19 18:06:29 +00:00
return res ? res : cmd ;
2002-03-01 16:54:59 +00:00
}
2003-11-13 01:47:23 +00:00
static int wait_file2 ( struct ast_channel * chan , struct vm_state * vms , char * file )
2002-06-28 15:21:23 +00:00
{
2003-11-13 01:47:23 +00:00
int res ;
if ( ( res = ast_streamfile ( chan , file , chan - > language ) ) )
ast_log ( LOG_WARNING , " Unable to play message %s \n " , file ) ;
if ( ! res )
res = ast_waitstream ( chan , AST_DIGIT_ANY ) ;
return res ;
}
2002-06-28 15:21:23 +00:00
2003-11-13 01:47:23 +00:00
static int wait_file ( struct ast_channel * chan , struct vm_state * vms , char * file )
{
int res ;
if ( ( res = ast_streamfile ( chan , file , chan - > language ) ) )
ast_log ( LOG_WARNING , " Unable to play message %s \n " , file ) ;
if ( ! res )
res = ast_waitstream_fr ( chan , AST_DIGIT_ANY , " # " , " * " , skipms ) ;
return res ;
}
static int play_message_datetime ( struct ast_channel * chan , struct ast_vm_user * vmu , struct vm_state * vms )
{
int res = 0 ;
char filename [ 256 ] , * origtime ;
struct vm_zone * the_zone = NULL ;
struct ast_config * msg_cfg ;
time_t t ;
long tin ;
make_file ( vms - > fn2 , sizeof ( vms - > fn2 ) , vms - > curdir , vms - > curmsg ) ;
snprintf ( filename , sizeof ( filename ) , " %s.txt " , vms - > fn2 ) ;
msg_cfg = ast_load ( filename ) ;
if ( ! msg_cfg ) {
ast_log ( LOG_WARNING , " No message attribute file?!! (%s) \n " , filename ) ;
return 0 ;
}
if ( ! ( origtime = ast_variable_retrieve ( msg_cfg , " message " , " origtime " ) ) )
return 0 ;
if ( sscanf ( origtime , " %ld " , & tin ) < 1 ) {
ast_log ( LOG_WARNING , " Couldn't find origtime in %s \n " , filename ) ;
return 0 ;
}
t = tin ;
ast_destroy ( msg_cfg ) ;
/* Does this user have a timezone specified? */
if ( strlen ( vmu - > zonetag ) ) {
/* Find the zone in the list */
struct vm_zone * z ;
z = zones ;
while ( z ) {
if ( ! strcmp ( z - > name , vmu - > zonetag ) ) {
the_zone = z ;
break ;
2002-06-28 15:21:23 +00:00
}
2003-11-13 01:47:23 +00:00
z = z - > next ;
2002-06-28 15:21:23 +00:00
}
2003-11-13 01:47:23 +00:00
}
2002-06-28 15:21:23 +00:00
2003-11-13 01:47:23 +00:00
/* No internal variable parsing for now, so we'll comment it out for the time being */
#if 0
/* Set the DIFF_* variables */
localtime_r ( & t , & time_now ) ;
gettimeofday ( & tv_now , NULL ) ;
tnow = tv_now . tv_sec ;
localtime_r ( & tnow , & time_then ) ;
/* Day difference */
if ( time_now . tm_year = = time_then . tm_year )
sprintf ( temp , " %d " , time_now . tm_yday ) ;
else
sprintf ( temp , " %d " , ( time_now . tm_year - time_then . tm_year ) * 365 + ( time_now . tm_yday - time_then . tm_yday ) ) ;
pbx_builtin_setvar_helper ( chan , " DIFF_DAY " , temp ) ;
2002-06-28 15:21:23 +00:00
2003-11-13 01:47:23 +00:00
/* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
# endif
if ( the_zone )
res = ast_say_date_with_format ( chan , t , AST_DIGIT_ANY , chan - > language , the_zone - > msg_format , the_zone - > timezone ) ;
else
res = ast_say_date_with_format ( chan , t , AST_DIGIT_ANY , chan - > language , " 'vm-received' q 'digits/at' IMp " , NULL ) ;
#if 0
pbx_builtin_setvar_helper ( chan , " DIFF_DAY " , NULL ) ;
# endif
return res ;
}
2002-06-28 15:21:23 +00:00
2003-11-13 01:47:23 +00:00
static int play_message ( struct ast_channel * chan , struct ast_vm_user * vmu , struct vm_state * vms , int msg )
{
int res = 0 ;
vms - > starting = 0 ;
make_file ( vms - > fn , sizeof ( vms - > fn ) , vms - > curdir , msg ) ;
adsi_message ( chan , vms - > curbox , msg , vms - > lastmsg , vms - > deleted [ msg ] , vms - > fn ) ;
if ( ! msg )
res = wait_file2 ( chan , vms , " vm-first " ) ;
else if ( msg = = vms - > lastmsg )
res = wait_file2 ( chan , vms , " vm-last " ) ;
if ( ! res ) {
res = wait_file2 ( chan , vms , " vm-message " ) ;
if ( msg & & ( msg ! = vms - > lastmsg ) ) {
if ( ! res )
res = ast_say_number ( chan , msg + 1 , AST_DIGIT_ANY , chan - > language ) ;
}
}
if ( ! res )
res = play_message_datetime ( chan , vmu , vms ) ;
if ( ! res ) {
make_file ( vms - > fn , sizeof ( vms - > fn ) , vms - > curdir , msg ) ;
vms - > heard [ msg ] = 1 ;
res = wait_file ( chan , vms , vms - > fn ) ;
}
return res ;
}
static void open_mailbox ( struct vm_state * vms , struct ast_vm_user * vmu , int box )
{
strncpy ( vms - > curbox , mbox ( box ) , sizeof ( vms - > curbox ) - 1 ) ;
make_dir ( vms - > curdir , sizeof ( vms - > curdir ) , vmu - > context , vms - > username , vms - > curbox ) ;
vms - > lastmsg = count_messages ( vms - > curdir ) - 1 ;
snprintf ( vms - > vmbox , sizeof ( vms - > vmbox ) , " vm-%s " , vms - > curbox ) ;
}
static void close_mailbox ( struct vm_state * vms , struct ast_vm_user * vmu )
{
int x ;
char ntxt [ 256 ] = " " ;
char txt [ 256 ] = " " ;
if ( vms - > lastmsg > - 1 ) {
/* Get the deleted messages fixed */
vms - > curmsg = - 1 ;
for ( x = 0 ; x < MAXMSG ; x + + ) {
if ( ! vms - > deleted [ x ] & & ( strcasecmp ( vms - > curbox , " INBOX " ) | | ! vms - > heard [ x ] ) ) {
/* Save this message. It's not in INBOX or hasn't been heard */
make_file ( vms - > fn , sizeof ( vms - > fn ) , vms - > curdir , x ) ;
if ( ast_fileexists ( vms - > fn , NULL , NULL ) < 1 )
2002-06-28 15:21:23 +00:00
break ;
2003-11-13 01:47:23 +00:00
vms - > curmsg + + ;
make_file ( vms - > fn2 , sizeof ( vms - > fn2 ) , vms - > curdir , vms - > curmsg ) ;
if ( strcmp ( vms - > fn , vms - > fn2 ) ) {
snprintf ( txt , sizeof ( txt ) , " %s.txt " , vms - > fn ) ;
snprintf ( ntxt , sizeof ( ntxt ) , " %s.txt " , vms - > fn2 ) ;
ast_filerename ( vms - > fn , vms - > fn2 , NULL ) ;
rename ( txt , ntxt ) ;
}
} else if ( ! strcasecmp ( vms - > curbox , " INBOX " ) & & vms - > heard [ x ] & & ! vms - > deleted [ x ] ) {
/* Move to old folder before deleting */
save_to_folder ( vms - > curdir , x , vmu - > context , vms - > username , 1 ) ;
}
}
for ( x = vms - > curmsg + 1 ; x < = MAXMSG ; x + + ) {
make_file ( vms - > fn , sizeof ( vms - > fn ) , vms - > curdir , x ) ;
if ( ast_fileexists ( vms - > fn , NULL , NULL ) < 1 )
break ;
snprintf ( txt , sizeof ( txt ) , " %s.txt " , vms - > fn ) ;
ast_filedelete ( vms - > fn , NULL ) ;
unlink ( txt ) ;
}
}
memset ( vms - > deleted , 0 , sizeof ( vms - > deleted ) ) ;
memset ( vms - > heard , 0 , sizeof ( vms - > heard ) ) ;
}
2002-06-28 15:21:23 +00:00
2003-11-13 01:47:23 +00:00
static int vm_intro ( struct ast_channel * chan , struct vm_state * vms )
{
/* Introduce messages they have */
int res ;
res = play_and_wait ( chan , " vm-youhave " ) ;
if ( ! res ) {
if ( vms - > newmessages ) {
res = say_and_wait ( chan , vms - > newmessages ) ;
if ( ! res )
res = play_and_wait ( chan , " vm-INBOX " ) ;
if ( vms - > oldmessages & & ! res )
res = play_and_wait ( chan , " vm-and " ) ;
else if ( ! res ) {
if ( ( vms - > newmessages = = 1 ) )
res = play_and_wait ( chan , " vm-message " ) ;
else
res = play_and_wait ( chan , " vm-messages " ) ;
}
}
if ( ! res & & vms - > oldmessages ) {
res = say_and_wait ( chan , vms - > oldmessages ) ;
if ( ! res )
res = play_and_wait ( chan , " vm-Old " ) ;
if ( ! res ) {
if ( vms - > oldmessages = = 1 )
res = play_and_wait ( chan , " vm-message " ) ;
else
res = play_and_wait ( chan , " vm-messages " ) ;
}
}
if ( ! res ) {
if ( ! vms - > oldmessages & & ! vms - > newmessages ) {
res = play_and_wait ( chan , " vm-no " ) ;
if ( ! res )
res = play_and_wait ( chan , " vm-messages " ) ;
}
}
}
return res ;
2002-06-28 15:21:23 +00:00
}
2003-11-13 01:47:23 +00:00
static int vm_instructions ( struct ast_channel * chan , struct vm_state * vms )
{
int res = 0 ;
/* Play instructions and wait for new command */
while ( ! res ) {
if ( vms - > starting ) {
if ( vms - > lastmsg > - 1 ) {
res = play_and_wait ( chan , " vm-onefor " ) ;
if ( ! res )
res = play_and_wait ( chan , vms - > vmbox ) ;
if ( ! res )
res = play_and_wait ( chan , " vm-messages " ) ;
}
if ( ! res )
res = play_and_wait ( chan , " vm-opts " ) ;
} else {
if ( vms - > curmsg )
res = play_and_wait ( chan , " vm-prev " ) ;
if ( ! res )
res = play_and_wait ( chan , " vm-repeat " ) ;
if ( ! res & & ( vms - > curmsg ! = vms - > lastmsg ) )
res = play_and_wait ( chan , " vm-next " ) ;
if ( ! res ) {
if ( ! vms - > deleted [ vms - > curmsg ] )
res = play_and_wait ( chan , " vm-delete " ) ;
else
res = play_and_wait ( chan , " vm-undelete " ) ;
if ( ! res )
res = play_and_wait ( chan , " vm-toforward " ) ;
if ( ! res )
res = play_and_wait ( chan , " vm-savemessage " ) ;
}
}
if ( ! res )
res = play_and_wait ( chan , " vm-helpexit " ) ;
if ( ! res )
res = ast_waitfordigit ( chan , 6000 ) ;
if ( ! res ) {
vms - > repeats + + ;
if ( vms - > repeats > 2 ) {
res = play_and_wait ( chan , " vm-goodbye " ) ;
if ( ! res )
res = ' t ' ;
}
}
}
return res ;
}
2002-06-28 15:21:23 +00:00
2003-11-13 01:47:23 +00:00
static int vm_options ( struct ast_channel * chan , struct ast_vm_user * vmu , struct vm_state * vms , char * fmtc )
{
int cmd = 0 ;
int retries = 0 ;
char newpassword [ 80 ] = " " ;
char newpassword2 [ 80 ] = " " ;
char prefile [ 256 ] = " " ;
char buf [ 256 ] ;
int bytes = 0 ;
2002-06-28 15:21:23 +00:00
2003-11-13 01:47:23 +00:00
if ( adsi_available ( chan ) )
{
bytes + = adsi_logo ( buf + bytes ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 3 , ADSI_JUST_CENT , 0 , " Options Menu " , " " ) ;
bytes + = adsi_display ( buf + bytes , ADSI_COMM_PAGE , 4 , ADSI_JUST_CENT , 0 , " Not Done " , " " ) ;
bytes + = adsi_set_line ( buf + bytes , ADSI_COMM_PAGE , 1 ) ;
bytes + = adsi_voice_mode ( buf + bytes , 0 ) ;
adsi_transmit_message ( chan , buf , bytes , ADSI_MSG_DISPLAY ) ;
}
while ( ( cmd > = 0 ) & & ( cmd ! = ' t ' ) ) {
if ( cmd )
retries = 0 ;
switch ( cmd ) {
case ' 1 ' :
snprintf ( prefile , sizeof ( prefile ) , " voicemail/%s/%s/unavail " , vmu - > context , vms - > username ) ;
cmd = play_and_record ( chan , " vm-rec-unv " , prefile , maxgreet , fmtc ) ;
break ;
case ' 2 ' :
snprintf ( prefile , sizeof ( prefile ) , " voicemail/%s/%s/busy " , vmu - > context , vms - > username ) ;
cmd = play_and_record ( chan , " vm-rec-busy " , prefile , maxgreet , fmtc ) ;
break ;
case ' 3 ' :
snprintf ( prefile , sizeof ( prefile ) , " voicemail/%s/%s/greet " , vmu - > context , vms - > username ) ;
cmd = play_and_record ( chan , " vm-rec-name " , prefile , maxgreet , fmtc ) ;
break ;
case ' 4 ' :
newpassword [ 1 ] = ' \0 ' ;
newpassword [ 0 ] = cmd = play_and_wait ( chan , " vm-newpassword " ) ;
if ( cmd < 0 )
break ;
if ( ( cmd = ast_readstring ( chan , newpassword + strlen ( newpassword ) , sizeof ( newpassword ) - 1 , 2000 , 10000 , " # " ) ) < 0 ) {
break ;
}
newpassword2 [ 1 ] = ' \0 ' ;
newpassword2 [ 0 ] = cmd = play_and_wait ( chan , " vm-reenterpassword " ) ;
if ( cmd < 0 )
break ;
if ( ( cmd = ast_readstring ( chan , newpassword2 + strlen ( newpassword2 ) , sizeof ( newpassword2 ) - 1 , 2000 , 10000 , " # " ) ) ) {
break ;
}
if ( strcmp ( newpassword , newpassword2 ) ) {
ast_log ( LOG_NOTICE , " Password mismatch for user %s (%s != %s) \n " , vms - > username , newpassword , newpassword2 ) ;
cmd = play_and_wait ( chan , " vm-mismatch " ) ;
break ;
}
vm_change_password ( vmu , newpassword ) ;
ast_log ( LOG_DEBUG , " User %s set password to %s of length %i \n " , vms - > username , newpassword , strlen ( newpassword ) ) ;
cmd = play_and_wait ( chan , " vm-passchanged " ) ;
break ;
case ' * ' :
cmd = ' t ' ;
break ;
default :
cmd = play_and_wait ( chan , " vm-options " ) ;
if ( ! cmd )
cmd = ast_waitfordigit ( chan , 6000 ) ;
if ( ! cmd )
retries + + ;
if ( retries > 3 )
cmd = ' t ' ;
}
}
if ( cmd = = ' t ' )
cmd = 0 ;
return cmd ;
}
2001-12-27 11:07:33 +00:00
1999-11-21 21:15:14 +00:00
static int vm_execmain ( struct ast_channel * chan , void * data )
{
2001-08-05 21:46:13 +00:00
/* XXX This is, admittedly, some pretty horrendus code. For some
reason it just seemed a lot easier to do with GOTO ' s . I feel
like I ' m back in my GWBASIC days . XXX */
1999-11-21 21:15:14 +00:00
int res = - 1 ;
int valid = 0 ;
2003-01-30 15:03:20 +00:00
int prefix = 0 ;
2003-11-13 01:47:23 +00:00
int cmd = 0 ;
1999-11-21 21:15:14 +00:00
struct localuser * u ;
2003-01-30 15:03:20 +00:00
char prefixstr [ 80 ] = " " ;
char empty [ 80 ] = " " ;
2001-08-05 21:46:13 +00:00
int box ;
2001-12-27 11:07:33 +00:00
int useadsi = 0 ;
2003-01-30 15:03:20 +00:00
int skipuser = 0 ;
char tmp [ 256 ] , * ext ;
2003-11-13 01:47:23 +00:00
char fmtc [ 256 ] = " " ;
char password [ 80 ] ;
struct vm_state vms ;
int logretries = 0 ;
struct ast_vm_user * vmu = NULL , vmus ;
char * context = NULL ;
2002-03-01 16:54:59 +00:00
1999-11-21 21:15:14 +00:00
LOCAL_USER_ADD ( u ) ;
2003-11-13 01:47:23 +00:00
memset ( & vms , 0 , sizeof ( vms ) ) ;
strncpy ( fmtc , vmfmts , sizeof ( fmtc ) - 1 ) ;
2002-07-31 20:34:22 +00:00
if ( chan - > _state ! = AST_STATE_UP )
2001-05-08 16:21:08 +00:00
ast_answer ( chan ) ;
2001-12-27 11:07:33 +00:00
2003-11-13 01:47:23 +00:00
if ( data & & strlen ( data ) ) {
2003-01-30 15:03:20 +00:00
strncpy ( tmp , data , sizeof ( tmp ) - 1 ) ;
ext = tmp ;
switch ( * ext ) {
case ' s ' :
/* We should skip the user's password */
valid + + ;
ext + + ;
break ;
case ' p ' :
/* We should prefix the mailbox with the supplied data */
prefix + + ;
ext + + ;
break ;
}
2003-11-13 01:47:23 +00:00
context = strchr ( ext , ' @ ' ) ;
if ( context ) {
* context = ' \0 ' ;
context + + ;
}
2003-01-30 15:03:20 +00:00
if ( prefix )
strncpy ( prefixstr , ext , sizeof ( prefixstr ) - 1 ) ;
else
2003-11-13 01:47:23 +00:00
strncpy ( vms . username , ext , sizeof ( vms . username ) - 1 ) ;
if ( strlen ( vms . username ) & & ( vmu = find_user ( & vmus , context , vms . username ) ) )
2003-01-30 15:03:20 +00:00
skipuser + + ;
else
valid = 0 ;
}
2001-12-27 11:07:33 +00:00
/* If ADSI is supported, setup login screen */
adsi_begin ( chan , & useadsi ) ;
2003-01-30 15:03:20 +00:00
if ( ! skipuser & & useadsi )
2001-12-27 11:07:33 +00:00
adsi_login ( chan ) ;
2003-01-30 15:03:20 +00:00
if ( ! skipuser & & ast_streamfile ( chan , " vm-login " , chan - > language ) ) {
2000-01-02 20:59:00 +00:00
ast_log ( LOG_WARNING , " Couldn't stream login file \n " ) ;
1999-11-21 21:15:14 +00:00
goto out ;
2000-01-02 20:59:00 +00:00
}
2001-08-05 21:46:13 +00:00
/* Authenticate them and get their mailbox/password */
2003-11-13 01:47:23 +00:00
while ( ! valid & & ( logretries < maxlogins ) ) {
1999-11-21 21:15:14 +00:00
/* Prompt for, and read in the username */
2003-11-13 01:47:23 +00:00
if ( ! skipuser & & ast_readstring ( chan , vms . username , sizeof ( vms . username ) - 1 , 2000 , 10000 , " # " ) < 0 ) {
2000-01-02 20:59:00 +00:00
ast_log ( LOG_WARNING , " Couldn't read username \n " ) ;
1999-11-21 21:15:14 +00:00
goto out ;
2003-01-30 15:03:20 +00:00
}
2003-11-13 01:47:23 +00:00
if ( ! strlen ( vms . username ) ) {
2000-01-02 20:59:00 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Username not entered \n " ) ;
1999-12-18 07:01:48 +00:00
res = 0 ;
goto out ;
}
2001-12-27 11:07:33 +00:00
if ( useadsi )
adsi_password ( chan ) ;
2000-01-09 19:58:18 +00:00
if ( ast_streamfile ( chan , " vm-password " , chan - > language ) ) {
2000-01-02 20:59:00 +00:00
ast_log ( LOG_WARNING , " Unable to stream password file \n " ) ;
1999-11-21 21:15:14 +00:00
goto out ;
2000-01-02 20:59:00 +00:00
}
2002-03-01 16:54:59 +00:00
if ( ast_readstring ( chan , password , sizeof ( password ) - 1 , 2000 , 10000 , " # " ) < 0 ) {
2000-01-02 20:59:00 +00:00
ast_log ( LOG_WARNING , " Unable to read password \n " ) ;
1999-11-21 21:15:14 +00:00
goto out ;
2000-01-02 20:59:00 +00:00
}
2003-01-30 15:03:20 +00:00
if ( prefix ) {
char fullusername [ 80 ] = " " ;
strncpy ( fullusername , prefixstr , sizeof ( fullusername ) - 1 ) ;
2003-11-13 01:47:23 +00:00
strncat ( fullusername , vms . username , sizeof ( fullusername ) - 1 ) ;
strncpy ( vms . username , fullusername , sizeof ( vms . username ) - 1 ) ;
}
if ( ! skipuser )
vmu = find_user ( & vmus , context , vms . username ) ;
if ( vmu & & ! strcmp ( vmu - > password , password ) )
valid + + ;
else {
2003-01-30 15:03:20 +00:00
if ( option_verbose > 2 )
2003-11-13 01:47:23 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Incorrect password '%s' for user '%s' (context = %s) \n " , password , vms . username , context ? context : " <any> " ) ;
if ( prefix )
strncpy ( vms . username , empty , sizeof ( vms . username ) - 1 ) ;
2003-01-30 15:03:20 +00:00
}
1999-11-21 21:15:14 +00:00
if ( ! valid ) {
2001-12-27 11:07:33 +00:00
if ( useadsi )
adsi_login ( chan ) ;
2000-01-09 19:58:18 +00:00
if ( ast_streamfile ( chan , " vm-incorrect " , chan - > language ) )
1999-11-21 21:15:14 +00:00
break ;
}
2003-11-13 01:47:23 +00:00
logretries + + ;
}
if ( ! valid & & ( logretries > = maxlogins ) ) {
ast_stopstream ( chan ) ;
res = play_and_wait ( chan , " vm-goodbye " ) ;
if ( res > 0 )
res = 0 ;
2003-01-30 15:03:20 +00:00
}
1999-11-21 21:15:14 +00:00
2001-08-05 21:46:13 +00:00
if ( valid ) {
2003-11-13 01:47:23 +00:00
snprintf ( vms . curdir , sizeof ( vms . curdir ) , " %s/voicemail/%s " , ( char * ) ast_config_AST_SPOOL_DIR , vmu - > context ) ;
mkdir ( vms . curdir , 0700 ) ;
snprintf ( vms . curdir , sizeof ( vms . curdir ) , " %s/voicemail/%s/%s " , ( char * ) ast_config_AST_SPOOL_DIR , vmu - > context , vms . username ) ;
mkdir ( vms . curdir , 0700 ) ;
/* Retrieve old and new message counts */
open_mailbox ( & vms , vmu , 1 ) ;
vms . oldmessages = vms . lastmsg + 1 ;
2001-08-05 21:46:13 +00:00
/* Start in INBOX */
2003-11-13 01:47:23 +00:00
open_mailbox ( & vms , vmu , 0 ) ;
vms . newmessages = vms . lastmsg + 1 ;
2001-08-05 21:46:13 +00:00
2001-12-27 11:07:33 +00:00
/* Select proper mailbox FIRST!! */
2003-11-13 01:47:23 +00:00
if ( ! vms . newmessages & & vms . oldmessages ) {
2001-12-27 11:07:33 +00:00
/* If we only have old messages start here */
2003-11-13 01:47:23 +00:00
open_mailbox ( & vms , vmu , 1 ) ;
2001-12-27 11:07:33 +00:00
}
if ( useadsi )
2003-11-13 01:47:23 +00:00
adsi_status ( chan , vms . newmessages , vms . oldmessages , vms . lastmsg ) ;
res = 0 ;
cmd = vm_intro ( chan , & vms ) ;
vms . repeats = 0 ;
vms . starting = 1 ;
while ( ( cmd > - 1 ) & & ( cmd ! = ' t ' ) & & ( cmd ! = ' # ' ) ) {
/* Run main menu */
switch ( cmd ) {
case ' 1 ' :
vms . curmsg = 0 ;
/* Fall through */
case ' 5 ' :
if ( vms . lastmsg > - 1 ) {
cmd = play_message ( chan , vmu , & vms , vms . curmsg ) ;
} else {
cmd = play_and_wait ( chan , " vm-youhave " ) ;
if ( ! cmd )
cmd = play_and_wait ( chan , " vm-no " ) ;
if ( ! cmd ) {
snprintf ( vms . fn , sizeof ( vms . fn ) , " vm-%s " , vms . curbox ) ;
cmd = play_and_wait ( chan , vms . fn ) ;
}
if ( ! cmd )
cmd = play_and_wait ( chan , " vm-messages " ) ;
}
break ;
case ' 2 ' : /* Change folders */
if ( useadsi )
adsi_folders ( chan , 0 , " Change to folder... " ) ;
cmd = get_folder2 ( chan , " vm-changeto " , 0 ) ;
if ( cmd = = ' # ' ) {
cmd = 0 ;
} else if ( cmd > 0 ) {
cmd = cmd - ' 0 ' ;
close_mailbox ( & vms , vmu ) ;
open_mailbox ( & vms , vmu , cmd ) ;
cmd = 0 ;
}
if ( useadsi )
adsi_status2 ( chan , vms . curbox , vms . lastmsg + 1 ) ;
if ( ! cmd )
cmd = play_and_wait ( chan , vms . vmbox ) ;
if ( ! cmd )
cmd = play_and_wait ( chan , " vm-messages " ) ;
vms . starting = 1 ;
break ;
case ' 4 ' :
if ( vms . curmsg ) {
vms . curmsg - - ;
cmd = play_message ( chan , vmu , & vms , vms . curmsg ) ;
} else {
cmd = play_and_wait ( chan , " vm-nomore " ) ;
}
break ;
case ' 6 ' :
if ( vms . curmsg < vms . lastmsg ) {
vms . curmsg + + ;
cmd = play_message ( chan , vmu , & vms , vms . curmsg ) ;
} else {
cmd = play_and_wait ( chan , " vm-nomore " ) ;
}
break ;
case ' 7 ' :
vms . deleted [ vms . curmsg ] = ! vms . deleted [ vms . curmsg ] ;
if ( useadsi )
adsi_delete ( chan , vms . curmsg , vms . lastmsg , vms . deleted [ vms . curmsg ] ) ;
if ( vms . deleted [ vms . curmsg ] )
cmd = play_and_wait ( chan , " vm-deleted " ) ;
2001-12-27 11:07:33 +00:00
else
2003-11-13 01:47:23 +00:00
cmd = play_and_wait ( chan , " vm-undeleted " ) ;
break ;
case ' 8 ' :
if ( vms . lastmsg > - 1 )
cmd = forward_message ( chan , context , vms . curdir , vms . curmsg , vmu , vmfmts ) ;
else
cmd = play_and_wait ( chan , " vm-nomore " ) ;
break ;
case ' 9 ' :
if ( useadsi )
adsi_folders ( chan , 1 , " Save to folder... " ) ;
cmd = get_folder2 ( chan , " vm-savefolder " , 1 ) ;
box = 0 ; /* Shut up compiler */
if ( cmd = = ' # ' ) {
cmd = 0 ;
break ;
} else if ( cmd > 0 ) {
box = cmd = cmd - ' 0 ' ;
cmd = save_to_folder ( vms . curdir , vms . curmsg , vmu - > context , vms . username , cmd ) ;
vms . deleted [ vms . curmsg ] = 1 ;
}
make_file ( vms . fn , sizeof ( vms . fn ) , vms . curdir , vms . curmsg ) ;
if ( useadsi )
adsi_message ( chan , vms . curbox , vms . curmsg , vms . lastmsg , vms . deleted [ vms . curmsg ] , vms . fn ) ;
if ( ! cmd )
cmd = play_and_wait ( chan , " vm-message " ) ;
if ( ! cmd )
cmd = say_and_wait ( chan , vms . curmsg + 1 ) ;
if ( ! cmd )
cmd = play_and_wait ( chan , " vm-savedto " ) ;
if ( ! cmd ) {
snprintf ( vms . fn , sizeof ( vms . fn ) , " vm-%s " , mbox ( box ) ) ;
cmd = play_and_wait ( chan , vms . fn ) ;
}
if ( ! cmd )
cmd = play_and_wait ( chan , " vm-messages " ) ;
break ;
case ' * ' :
if ( ! vms . starting ) {
cmd = play_and_wait ( chan , " vm-onefor " ) ;
if ( ! cmd )
cmd = play_and_wait ( chan , vms . vmbox ) ;
if ( ! cmd )
cmd = play_and_wait ( chan , " vm-messages " ) ;
if ( ! cmd )
cmd = play_and_wait ( chan , " vm-opts " ) ;
} else
cmd = 0 ;
break ;
case ' 0 ' :
cmd = vm_options ( chan , vmu , & vms , vmfmts ) ;
if ( useadsi )
adsi_status ( chan , vms . newmessages , vms . oldmessages , vms . lastmsg ) ;
break ;
default : /* Nothing */
cmd = vm_instructions ( chan , & vms ) ;
break ;
2001-08-05 21:46:13 +00:00
}
}
2003-11-13 01:47:23 +00:00
if ( ( cmd = = ' t ' ) | | ( cmd = = ' # ' ) ) {
/* Timeout */
2001-12-27 11:07:33 +00:00
res = 0 ;
2003-11-13 01:47:23 +00:00
} else {
/* Hangup */
res = - 1 ;
1999-11-21 21:15:14 +00:00
}
}
out :
2003-11-13 01:47:23 +00:00
if ( res > - 1 ) {
ast_stopstream ( chan ) ;
adsi_goodbye ( chan ) ;
if ( valid ) {
res = play_and_wait ( chan , " vm-goodbye " ) ;
if ( res > 0 )
res = 0 ;
}
if ( useadsi )
adsi_unload_session ( chan ) ;
}
if ( vmu )
close_mailbox ( & vms , vmu ) ;
if ( vmu )
free_user ( vmu ) ;
2003-02-24 06:00:18 +00:00
if ( valid ) {
2003-11-13 01:47:23 +00:00
manager_event ( EVENT_FLAG_CALL , " MessageWaiting " , " Mailbox: %s \r \n Waiting: %d \r \n " , vms . username , ast_app_has_voicemail ( vms . username ) ) ;
2003-02-24 06:00:18 +00:00
}
1999-11-21 21:15:14 +00:00
LOCAL_USER_REMOVE ( u ) ;
return res ;
2002-06-28 15:21:23 +00:00
1999-11-21 21:15:14 +00:00
}
static int vm_exec ( struct ast_channel * chan , void * data )
{
2001-12-27 11:07:33 +00:00
int res = 0 , silent = 0 , busy = 0 , unavail = 0 ;
1999-11-21 21:15:14 +00:00
struct localuser * u ;
2003-01-30 15:03:20 +00:00
char tmp [ 256 ] , * ext ;
1999-11-21 21:15:14 +00:00
LOCAL_USER_ADD ( u ) ;
2003-01-30 15:03:20 +00:00
if ( chan - > _state ! = AST_STATE_UP )
ast_answer ( chan ) ;
2003-11-21 05:50:21 +00:00
if ( data & & strlen ( data ) )
2003-01-30 15:03:20 +00:00
strncpy ( tmp , data , sizeof ( tmp ) - 1 ) ;
else {
res = ast_app_getdata ( chan , " vm-whichbox " , tmp , sizeof ( tmp ) - 1 , 0 ) ;
if ( res < 0 )
return res ;
if ( ! strlen ( tmp ) )
return 0 ;
}
ext = tmp ;
2003-11-13 01:47:23 +00:00
while ( * ext ) {
if ( * ext = = ' s ' ) {
silent = 2 ;
ext + + ;
} else if ( * ext = = ' b ' ) {
busy = 1 ;
ext + + ;
} else if ( * ext = = ' u ' ) {
unavail = 1 ;
ext + + ;
} else
break ;
1999-11-21 21:15:14 +00:00
}
2001-12-27 11:07:33 +00:00
res = leave_voicemail ( chan , ext , silent , busy , unavail ) ;
1999-11-21 21:15:14 +00:00
LOCAL_USER_REMOVE ( u ) ;
return res ;
}
2003-11-13 01:47:23 +00:00
static int append_mailbox ( char * context , char * mbox , char * data )
{
/* Assumes lock is already held */
char tmp [ 256 ] = " " ;
char * stringp ;
char * s ;
struct ast_vm_user * vmu ;
strncpy ( tmp , data , sizeof ( tmp ) ) ;
vmu = malloc ( sizeof ( struct ast_vm_user ) ) ;
if ( vmu ) {
memset ( vmu , 0 , sizeof ( struct ast_vm_user ) ) ;
strncpy ( vmu - > context , context , sizeof ( vmu - > context ) ) ;
strncpy ( vmu - > mailbox , mbox , sizeof ( vmu - > mailbox ) ) ;
vmu - > attach = - 1 ;
stringp = tmp ;
if ( ( s = strsep ( & stringp , " , " ) ) )
strncpy ( vmu - > password , s , sizeof ( vmu - > password ) ) ;
if ( stringp & & ( s = strsep ( & stringp , " , " ) ) )
strncpy ( vmu - > fullname , s , sizeof ( vmu - > fullname ) ) ;
if ( stringp & & ( s = strsep ( & stringp , " , " ) ) )
strncpy ( vmu - > email , s , sizeof ( vmu - > email ) ) ;
if ( stringp & & ( s = strsep ( & stringp , " , " ) ) )
strncpy ( vmu - > pager , s , sizeof ( vmu - > pager ) ) ;
if ( stringp & & ( s = strsep ( & stringp , " , " ) ) )
apply_options ( vmu , s ) ;
vmu - > next = NULL ;
if ( usersl )
usersl - > next = vmu ;
else
users = vmu ;
usersl = vmu ;
}
return 0 ;
}
static int load_config ( void )
{
struct ast_vm_user * cur , * l ;
struct vm_zone * zcur , * zl ;
struct ast_config * cfg ;
char * cat ;
struct ast_variable * var ;
char * astattach ;
char * silencestr ;
char * thresholdstr ;
char * fmt ;
char * astemail ;
char * s ;
int x ;
cfg = ast_load ( VOICEMAIL_CONFIG ) ;
ast_mutex_lock ( & vmlock ) ;
cur = users ;
while ( cur ) {
l = cur ;
cur = cur - > next ;
free_user ( l ) ;
}
zcur = zones ;
while ( zcur ) {
zl = zcur ;
zcur = zcur - > next ;
free_zone ( zl ) ;
}
zones = NULL ;
zonesl = NULL ;
users = NULL ;
usersl = NULL ;
if ( cfg ) {
/* General settings */
attach_voicemail = 1 ;
if ( ! ( astattach = ast_variable_retrieve ( cfg , " general " , " attach " ) ) )
astattach = " yes " ;
attach_voicemail = ast_true ( astattach ) ;
maxsilence = 0 ;
if ( ( silencestr = ast_variable_retrieve ( cfg , " general " , " maxsilence " ) ) ) {
maxsilence = atoi ( silencestr ) ;
if ( maxsilence > 0 )
maxsilence * = 1000 ;
}
silencethreshold = 256 ;
if ( ( thresholdstr = ast_variable_retrieve ( cfg , " general " , " silencethreshold " ) ) )
silencethreshold = atoi ( thresholdstr ) ;
if ( ! ( astemail = ast_variable_retrieve ( cfg , " general " , " serveremail " ) ) )
astemail = ASTERISK_USERNAME ;
strncpy ( serveremail , astemail , sizeof ( serveremail ) - 1 ) ;
vmmaxmessage = 0 ;
if ( ( s = ast_variable_retrieve ( cfg , " general " , " maxmessage " ) ) ) {
if ( sscanf ( s , " %d " , & x ) = = 1 ) {
vmmaxmessage = x ;
} else {
ast_log ( LOG_WARNING , " Invalid max message time length \n " ) ;
}
}
fmt = ast_variable_retrieve ( cfg , " general " , " format " ) ;
if ( ! fmt )
fmt = " wav " ;
strncpy ( vmfmts , fmt , sizeof ( vmfmts ) - 1 ) ;
skipms = 3000 ;
if ( ( s = ast_variable_retrieve ( cfg , " general " , " maxgreet " ) ) ) {
if ( sscanf ( s , " %d " , & x ) = = 1 ) {
maxgreet = x ;
} else {
ast_log ( LOG_WARNING , " Invalid max message greeting length \n " ) ;
}
}
if ( ( s = ast_variable_retrieve ( cfg , " general " , " skipms " ) ) ) {
if ( sscanf ( s , " %d " , & x ) = = 1 ) {
skipms = x ;
} else {
ast_log ( LOG_WARNING , " Invalid skipms value \n " ) ;
}
}
maxlogins = 3 ;
if ( ( s = ast_variable_retrieve ( cfg , " general " , " maxlogins " ) ) ) {
if ( sscanf ( s , " %d " , & x ) = = 1 ) {
maxlogins = x ;
} else {
ast_log ( LOG_WARNING , " Invalid max failed login attempts \n " ) ;
}
}
# ifdef USEMYSQLVM
if ( ! ( s = ast_variable_retrieve ( cfg , " general " , " dbuser " ) ) ) {
strcpy ( dbuser , " test " ) ;
} else {
strcpy ( dbuser , s ) ;
}
if ( ! ( s = ast_variable_retrieve ( cfg , " general " , " dbpass " ) ) ) {
strcpy ( dbpass , " test " ) ;
} else {
strcpy ( dbpass , s ) ;
}
if ( ! ( s = ast_variable_retrieve ( cfg , " general " , " dbhost " ) ) ) {
strcpy ( dbhost , " " ) ;
} else {
strcpy ( dbhost , s ) ;
}
if ( ! ( s = ast_variable_retrieve ( cfg , " general " , " dbname " ) ) ) {
strcpy ( dbname , " vmdb " ) ;
} else {
strcpy ( dbname , s ) ;
}
# endif
# ifdef USEPOSTGRESVM
if ( ! ( s = ast_variable_retrieve ( cfg , " general " , " dboption " ) ) ) {
strcpy ( dboption , " dboption not-specified in voicemail.conf " ) ;
} else {
strcpy ( dboption , s ) ;
}
# endif
cat = ast_category_browse ( cfg , NULL ) ;
while ( cat ) {
if ( strcasecmp ( cat , " general " ) ) {
var = ast_variable_browse ( cfg , cat ) ;
if ( strcasecmp ( cat , " zonemessages " ) ) {
# ifndef USESQLVM
/* Process mailboxes in this context */
while ( var ) {
append_mailbox ( cat , var - > name , var - > value ) ;
var = var - > next ;
}
# endif
} else {
/* Timezones in this context */
while ( var ) {
struct vm_zone * z ;
z = malloc ( sizeof ( struct vm_zone ) ) ;
if ( z ! = NULL ) {
char * msg_format , * timezone ;
msg_format = ast_strdupa ( var - > value ) ;
if ( msg_format ! = NULL ) {
timezone = strsep ( & msg_format , " | " ) ;
strncpy ( z - > name , var - > name , sizeof ( z - > name ) - 1 ) ;
strncpy ( z - > timezone , timezone , sizeof ( z - > timezone ) - 1 ) ;
strncpy ( z - > msg_format , msg_format , sizeof ( z - > msg_format ) - 1 ) ;
z - > next = NULL ;
if ( zones ) {
zonesl - > next = z ;
zonesl = z ;
} else {
zones = z ;
zonesl = z ;
}
} else {
ast_log ( LOG_WARNING , " Out of memory while reading voicemail config \n " ) ;
free ( z ) ;
return - 1 ;
}
} else {
ast_log ( LOG_WARNING , " Out of memory while reading voicemail config \n " ) ;
return - 1 ;
}
var = var - > next ;
}
}
}
cat = ast_category_browse ( cfg , cat ) ;
}
memset ( fromstring , 0 , sizeof ( fromstring ) ) ;
memset ( emailtitle , 0 , sizeof ( emailtitle ) ) ;
if ( emailbody ) {
free ( emailbody ) ;
emailbody = NULL ;
}
if ( ( s = ast_variable_retrieve ( cfg , " general " , " pbxskip " ) ) )
pbxskip = ast_true ( s ) ;
if ( ( s = ast_variable_retrieve ( cfg , " general " , " fromstring " ) ) )
strncpy ( fromstring , s , sizeof ( fromstring ) - 1 ) ;
if ( ( s = ast_variable_retrieve ( cfg , " general " , " emailtitle " ) ) )
strncpy ( emailtitle , s , sizeof ( emailtitle ) - 1 ) ;
if ( ( s = ast_variable_retrieve ( cfg , " general " , " emailbody " ) ) ) {
char * tmpread , * tmpwrite ;
emailbody = strdup ( s ) ;
/* substitute strings \t and \n into the apropriate characters */
tmpread = tmpwrite = emailbody ;
while ( ( tmpwrite = strchr ( tmpread , ' \\ ' ) ) ) {
int len = strlen ( " \n " ) ;
switch ( tmpwrite [ 1 ] ) {
case ' n ' :
strncpy ( tmpwrite + len , tmpwrite + 2 , strlen ( tmpwrite + 2 ) + 1 ) ;
strncpy ( tmpwrite , " \n " , len ) ;
break ;
case ' t ' :
strncpy ( tmpwrite + len , tmpwrite + 2 , strlen ( tmpwrite + 2 ) + 1 ) ;
strncpy ( tmpwrite , " \t " , len ) ;
break ;
default :
ast_log ( LOG_NOTICE , " Substitution routine does not support this character: %c \n " , tmpwrite [ 1 ] ) ;
}
tmpread = tmpwrite + len ;
}
}
ast_destroy ( cfg ) ;
ast_mutex_unlock ( & vmlock ) ;
return 0 ;
} else {
ast_mutex_unlock ( & vmlock ) ;
ast_log ( LOG_WARNING , " Error reading voicemail config \n " ) ;
return - 1 ;
}
}
int reload ( void )
{
return ( load_config ( ) ) ;
}
1999-11-21 21:15:14 +00:00
int unload_module ( void )
{
int res ;
STANDARD_HANGUP_LOCALUSERS ;
res = ast_unregister_application ( app ) ;
2003-11-17 06:20:09 +00:00
res | = ast_unregister_application ( capp ) ;
1999-11-21 21:15:14 +00:00
res | = ast_unregister_application ( app2 ) ;
2003-11-17 06:20:09 +00:00
res | = ast_unregister_application ( capp2 ) ;
2003-11-13 01:47:23 +00:00
sql_close ( ) ;
1999-11-21 21:15:14 +00:00
return res ;
}
int load_module ( void )
{
int res ;
2001-05-08 16:21:08 +00:00
res = ast_register_application ( app , vm_exec , synopsis_vm , descrip_vm ) ;
2003-11-13 01:47:23 +00:00
res | = ast_register_application ( capp , vm_exec , synopsis_vm , descrip_vm ) ;
res | = ast_register_application ( app2 , vm_execmain , synopsis_vmain , descrip_vmain ) ;
res | = ast_register_application ( capp2 , vm_execmain , synopsis_vmain , descrip_vmain ) ;
if ( res )
return ( res ) ;
if ( ( res = load_config ( ) ) ) {
return ( res ) ;
}
if ( ( res = sql_init ( ) ) ) {
ast_log ( LOG_WARNING , " SQL init \n " ) ;
return res ;
}
1999-11-21 21:15:14 +00:00
return res ;
}
char * description ( void )
{
return tdesc ;
}
int usecount ( void )
{
int res ;
STANDARD_USECOUNT ( res ) ;
return res ;
}
2001-03-10 19:12:11 +00:00
char * key ( )
{
return ASTERISK_GPL_KEY ;
}