aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-11-13 01:47:23 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-11-13 01:47:23 +0000
commit031a2bae1d243c964ef487a482775c9215c99090 (patch)
tree1c2e5619f3f5fd04fa74c12b36c6e48a7af56d6e /apps
parent5244329d3c18aa5f9443c8b2ad162c6b2876e9ac (diff)
Move voicemail2 to voicemail, retain compatibility with "Voicemail2"
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1735 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rwxr-xr-xapps/Makefile2
-rwxr-xr-xapps/app_voicemail.c2700
-rwxr-xr-xapps/app_voicemail2.c2965
3 files changed, 1684 insertions, 3983 deletions
diff --git a/apps/Makefile b/apps/Makefile
index daba282d2..c3910a74a 100755
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -23,7 +23,7 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\
app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \
app_authenticate.so app_softhangup.so app_lookupblacklist.so \
app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \
- app_enumlookup.so app_voicemail2.so app_transfer.so app_setcidnum.so app_cdr.so \
+ app_enumlookup.so app_transfer.so app_setcidnum.so app_cdr.so \
app_hasnewvoicemail.so app_sayunixtime.so app_cut.so app_read.so
ifneq (${OSARCH},Darwin)
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 8c2a23f9d..0b45b0133 100755
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -3,9 +3,9 @@
*
* Voicemail System (did you ever think it could be so easy?)
*
- * Copyright (C) 1999, Mark Spencer
+ * Copyright (C) 2003, Digium Inc.
*
- * Mark Spencer <markster@linux-support.net>
+ * Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
@@ -15,6 +15,7 @@
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
+#include <asterisk/channel_pvt.h>
#include <asterisk/pbx.h>
#include <asterisk/options.h>
#include <asterisk/config.h>
@@ -24,6 +25,7 @@
#include <asterisk/app.h>
#include <asterisk/manager.h>
#include <asterisk/dsp.h>
+#include <asterisk/localtime.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
@@ -34,6 +36,25 @@
#include <sys/stat.h>
#include <time.h>
+/* 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
+
#include <pthread.h>
#include "../asterisk.h"
#include "../astconf.h"
@@ -48,28 +69,45 @@
#define INTRO "vm-intro"
#define MAXMSG 100
-
#define MAX_OTHER_FORMATS 10
#define VM_SPOOL_DIR AST_SPOOL_DIR "/vm"
#define BASEMAXINLINE 256
-
#define BASELINELEN 72
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
#define BASEMAXINLINE 256
-#define BASELINELEN 72
#define eol "\r\n"
-static int iocp;
-static int iolen;
-static int linelength;
-static int ateof;
-static unsigned char iobuf[BASEMAXINLINE];
+#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;
+};
static char *tdesc = "Comedian Mail (Voicemail System)";
@@ -85,51 +123,301 @@ static char *synopsis_vm =
"Leave a voicemail message";
static char *descrip_vm =
-" VoiceMail([s|u|b]extension): Leaves voicemail for a given extension (must\n"
-"be configured in voicemail.conf). If the extension is preceeded by an 's'"
-"then instructions for leaving the message will be skipped. If the extension\n"
-"is preceeded by 'u' then the \"unavailable\" message will be played (that is, \n"
-"/var/lib/asterisk/sounds/vm/<exten>/unavail) if it exists. If the extension\n"
-"is preceeded by a 'b' then the the busy message will be played (that is,\n"
-"busy instead of unavail). At most one of 's', 'u', or 'b' may be specified.\n"
-"Returns -1 on error or mailbox not found, or if the user hangs up. \n"
-"Otherwise, it returns 0. \n";
+" 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"
+"Returns -1 on error or mailbox not found, or if the user hangs up.\n"
+"Otherwise, it returns 0.\n";
static char *synopsis_vmain =
"Enter voicemail system";
static char *descrip_vmain =
-" VoiceMailMain(): Enters the main voicemail system for the checking of\n"
-"voicemail. The mailbox can be passed as the option, which will stop the\n"
-"voicemail system from prompting the user for the mailbox. If the mailbox\n"
-"is preceded by 's' then the password check will be skipped. Returns -1 if\n"
-"the user hangs up or 0 otherwise.\n";
+" 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";
/* Leave a message */
+static char *capp = "VoiceMail2";
static char *app = "VoiceMail";
/* Check mail, control, etc */
+static char *capp2 = "VoiceMailMain2";
static char *app2 = "VoiceMailMain";
+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];
+
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
-static int make_dir(char *dest, int len, char *ext, char *mailbox)
+static void apply_options(struct ast_vm_user *vmu, char *options)
+{
+ /* 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);
+ }
+ }
+ }
+
+}
+
+#ifdef USEMYSQLVM
+#include "mysql-vm-routines.h"
+#endif
+
+#ifdef USEPOSTGRESVM
+
+PGconn *dbhandler;
+char dboption[256];
+ast_mutex_t postgreslock;
+
+static int sql_init(void)
{
- return snprintf(dest, len, "%s/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR,"vm", ext, mailbox);
+ 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 int make_file(char *dest, int len, char *dir, int num)
+static void sql_close(void)
{
- return snprintf(dest, len, "%s/msg%04d", dir, num);
+ PQfinish(dbhandler);
}
-static int vm_change_password(char *username, char *password, char *newpassword)
+
+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);
+ }
+
+ if (*retval->context) {
+ sprintf(query, "SELECT password,fullname,email,pager,options FROM voicemail WHERE context='%s' AND mailbox='%s'", context, mailbox);
+ } else {
+ sprintf(query, "SELECT password,fullname,email,pager,options FROM voicemail WHERE mailbox='%s'", mailbox);
+ }
+/* 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;
+}
+
+static void vm_change_password(struct ast_vm_user *vmu, char *newpassword)
{
/* There's probably a better way of doing this. */
/* That's why I've put the password change in a separate function. */
-
+ /* This could also be done with a database function */
+
FILE *configin;
FILE *configout;
char inbuf[256];
@@ -137,10 +425,24 @@ static int vm_change_password(char *username, char *password, char *newpassword)
char tmpin[AST_CONFIG_MAX_PATH];
char tmpout[AST_CONFIG_MAX_PATH];
char *user, *pass, *rest, *trim;
- 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);
+ 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);
configin = fopen((char *)tmpin,"r");
- configout = fopen((char *)tmpout,"w+");
+ 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;
+ }
while (!feof(configin)) {
/* Read in the line */
@@ -180,12 +482,12 @@ static int vm_change_password(char *username, char *password, char *newpassword)
}
} else
rest = NULL;
- if (user && pass && *user && *pass && !strcmp(user, username) && !strcmp(pass, password)) {
+ if (user && pass && *user && *pass && !strcmp(user, vmu->mailbox) && !strcmp(pass, vmu->password)) {
/* This is the line */
if (rest) {
- fprintf(configout, "%s => %s,%s\n", username,newpassword,rest);
+ fprintf(configout, "%s => %s,%s\n", vmu->mailbox,newpassword,rest);
} else {
- fprintf(configout, "%s => %s\n", username,newpassword);
+ fprintf(configout, "%s => %s\n", vmu->mailbox,newpassword);
}
} else {
/* Put it back like it was */
@@ -198,55 +500,67 @@ static int vm_change_password(char *username, char *password, char *newpassword)
unlink((char *)tmpin);
rename((char *)tmpout,(char *)tmpin);
- return(1);
+ 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);
}
static int
-inbuf(FILE *fi)
+inbuf(struct baseio *bio, FILE *fi)
{
int l;
- if(ateof)
+ if(bio->ateof)
return 0;
- if ( (l = fread(iobuf,1,BASEMAXINLINE,fi)) <= 0) {
+ if ( (l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
if(ferror(fi))
return -1;
- ateof = 1;
+ bio->ateof = 1;
return 0;
}
- iolen= l;
- iocp= 0;
+ bio->iolen= l;
+ bio->iocp= 0;
return 1;
}
static int
-inchar(FILE *fi)
+inchar(struct baseio *bio, FILE *fi)
{
- if(iocp>=iolen)
- if(!inbuf(fi))
+ if(bio->iocp>=bio->iolen)
+ if(!inbuf(bio, fi))
return EOF;
- return iobuf[iocp++];
+ return bio->iobuf[bio->iocp++];
}
static int
-ochar(int c, FILE *so)
+ochar(struct baseio *bio, int c, FILE *so)
{
- if(linelength>=BASELINELEN) {
+ if(bio->linelength>=BASELINELEN) {
if(fputs(eol,so)==EOF)
return -1;
- linelength= 0;
+ bio->linelength= 0;
}
if(putc(((unsigned char)c),so)==EOF)
return -1;
- linelength++;
+ bio->linelength++;
return 1;
}
@@ -256,11 +570,10 @@ static int base_encode(char *filename, FILE *so)
unsigned char dtable[BASEMAXINLINE];
int i,hiteof= 0;
FILE *fi;
+ struct baseio bio;
- linelength = 0;
- iocp = BASEMAXINLINE;
- iolen = 0;
- ateof = 0;
+ memset(&bio, 0, sizeof(bio));
+ bio.iocp = BASEMAXINLINE;
if ( !(fi = fopen(filename, "rb"))) {
ast_log(LOG_WARNING, "Failed to open log file: %s: %s\n", filename, strerror(errno));
@@ -290,7 +603,7 @@ static int base_encode(char *filename, FILE *so)
igroup[0]= igroup[1]= igroup[2]= 0;
for(n= 0;n<3;n++){
- if ( (c = inchar(fi)) == EOF) {
+ if ( (c = inchar(&bio, fi)) == EOF) {
hiteof= 1;
break;
}
@@ -312,7 +625,7 @@ static int base_encode(char *filename, FILE *so)
}
for(i= 0;i<4;i++)
- ochar(ogroup[i], so);
+ ochar(&bio, ogroup[i], so);
}
}
@@ -324,7 +637,7 @@ static int base_encode(char *filename, FILE *so)
return 1;
}
-static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *mailbox, char *callerid, char *attach, char *format, long duration)
+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)
{
FILE *p;
char date[256];
@@ -335,12 +648,12 @@ static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *m
char dur[256];
time_t t;
struct tm tm;
- char *astattach;
- struct ast_config *cfg;
+ 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);
p = popen(SENDMAIL, "w");
- cfg = ast_load(VOICEMAIL_CONFIG);
- if (!(astattach = ast_variable_retrieve(cfg, "general", "attach")))
- astattach = "yes";
if (p) {
gethostname(host, sizeof(host));
if (strchr(srcemail, '@'))
@@ -350,15 +663,47 @@ static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *m
}
snprintf(dur, sizeof(dur), "%ld:%02ld", duration / 60, duration % 60);
time(&t);
- localtime_r(&t,&tm);
+
+ /* 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);
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 <%s>\n", name, email);
- fprintf(p, "Subject: [PBX]: New message %d in mailbox %s\n", msgnum, mailbox);
+
+ 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);
fprintf(p, "Message-ID: <Asterisk-%d-%s-%d@%s>\n", msgnum, mailbox, getpid(), host);
fprintf(p, "MIME-Version: 1.0\n");
- if (ast_true(astattach)) {
+ if (attach_user_voicemail) {
// Something unique.
snprintf(bound, sizeof(bound), "Boundary=%d%s%d", msgnum, mailbox, getpid());
@@ -366,16 +711,37 @@ static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *m
fprintf(p, "--%s\n", bound);
}
- fprintf(p, "Content-Type: TEXT/PLAIN; charset=US-ASCII\n\n");
- strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
+ 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 {
fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message (number %d)\n"
- "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", name,
- dur, msgnum, mailbox, (callerid ? callerid : "an unknown caller"), date);
- if (ast_true(astattach)) {
+ "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) {
fprintf(p, "--%s\n", bound);
- fprintf(p, "Content-Type: audio/x-wav; name=\"msg%04d.%s\"\n", msgnum, format);
+ fprintf(p, "Content-Type: audio/x-wav; name=\"msg%04d.%s\"\n", msgnum + 1, format);
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);
@@ -392,7 +758,7 @@ static int sendmail(char *srcemail, char *email, char *name, int msgnum, char *m
return 0;
}
-static int sendpage(char *srcemail, char *pager, int msgnum, char *mailbox, char *callerid, long duration)
+static int sendpage(char *srcemail, char *pager, int msgnum, char *mailbox, char *callerid, long duration, struct ast_vm_user *vmu)
{
FILE *p;
char date[256];
@@ -401,9 +767,8 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *mailbox, char
char dur[256];
time_t t;
struct tm tm;
- struct ast_config *cfg;
+ struct vm_zone *the_zone = NULL;
p = popen(SENDMAIL, "w");
- cfg = ast_load(VOICEMAIL_CONFIG);
if (p) {
gethostname(host, sizeof(host));
@@ -414,7 +779,26 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *mailbox, char
}
snprintf(dur, sizeof(dur), "%ld:%02ld", duration / 60, duration % 60);
time(&t);
- localtime_r(&t,&tm);
+
+ /* 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);
+
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);
@@ -440,11 +824,11 @@ static int get_date(char *s, int len)
return strftime(s, len, "%a %b %e %r %Z %Y", &tm);
}
-static int invent_message(struct ast_channel *chan, char *ext, int busy, char *ecodes)
+static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
{
int res;
char fn[256];
- snprintf(fn, sizeof(fn), "vm/%s/greet", ext);
+ snprintf(fn, sizeof(fn), "voicemail/%s/%s/greet", context, ext);
if (ast_fileexists(fn, NULL, NULL) > 0) {
res = ast_streamfile(chan, fn, chan->language);
if (res)
@@ -473,81 +857,256 @@ static int invent_message(struct ast_channel *chan, char *ext, int busy, char *e
return res;
}
-static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int busy, int unavail)
+static int play_and_wait(struct ast_channel *chan, char *fn)
{
- struct ast_config *cfg;
- char *copy, *name, *passwd, *email, *pager, *fmt, *fmts;
+ int d;
+ d = ast_streamfile(chan, fn, chan->language);
+ if (d)
+ return d;
+ d = ast_waitstream(chan, AST_DIGIT_ANY);
+ return d;
+}
+
+static int play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt)
+{
+ char d, *fmts;
char comment[256];
- struct ast_filestream *writer=NULL, *others[MAX_OTHER_FORMATS];
+ int x, fmtcnt=1, res=-1,outmsg=0;
+ struct ast_frame *f;
+ struct ast_filestream *others[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;
+
+ 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);
+ if (!d)
+ 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];
char txtfile[256];
FILE *txt;
- int res = -1, fmtcnt=0, x;
+ int res = 0;
int msgnum;
- int outmsg=0;
- int wavother=0;
- int maxmessage=0;
- struct ast_frame *f;
char date[256];
char dir[256];
char fn[256];
char prefile[256]="";
- char *astemail;
+ char fmt[80];
+ char *context;
char *ecodes = "#";
- char *s;
+ char *stringp;
time_t start;
time_t end;
- struct ast_dsp *sildet; /* silence detector dsp */
- int totalsilence = 0;
- int dspsilence = 0;
- int silence = 0; /* amount of silence to allow */
- int gotsilence = 0; /* did we timeout for silence? */
- char *silencestr;
- char *thresholdstr;
- int rfmt;
- int threshold = 128;
-
- cfg = ast_load(VOICEMAIL_CONFIG);
- if (!cfg) {
- ast_log(LOG_WARNING, "No such configuration file %s\n", VOICEMAIL_CONFIG);
- return -1;
- }
- if ((silencestr = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
- silence = atoi(silencestr);
- if (silence > 0)
- silence *= 1000;
- }
- if ((thresholdstr = ast_variable_retrieve(cfg, "general", "silencethreshold")))
- threshold = atoi(thresholdstr);
-
- if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail")))
- astemail = ASTERISK_USERNAME;
- if ((s = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
- if (sscanf(s, "%d", &x) == 1) {
- maxmessage = x;
- } else {
- ast_log(LOG_WARNING, "Invalid max message time length\n");
- }
+ 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++;
}
- if ((copy = ast_variable_retrieve(cfg, NULL, ext))) {
- char *stringp=NULL;
+
+ if ((vmu = find_user(&svm, context, ext))) {
/* Setup pre-file if appropriate */
if (busy)
- snprintf(prefile, sizeof(prefile), "vm/%s/busy", ext);
+ snprintf(prefile, sizeof(prefile), "voicemail/%s/%s/busy", vmu->context, ext);
else if (unavail)
- snprintf(prefile, sizeof(prefile), "vm/%s/unavail", ext);
- /* Make sure they have an entry in the config */
- copy = strdup(copy);
- stringp=copy;
- passwd = strsep(&stringp, ",");
- name = strsep(&stringp, ",");
- email = strsep(&stringp, ",");
- pager = strsep(&stringp, ",");
- make_dir(dir, sizeof(dir), ext, "");
+ 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), ext, "INBOX");
+ make_dir(dir, sizeof(dir), vmu->context, ext, "");
+ /* 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, "INBOX");
if (mkdir(dir, 0700) && (errno != EEXIST))
ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
if (ast_exists_extension(chan, strlen(chan->macrocontext) ? chan->macrocontext : chan->context, "o", 1, chan->callerid))
@@ -556,75 +1115,71 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
if (strlen(prefile)) {
if (ast_fileexists(prefile, NULL, NULL) > 0) {
if (ast_streamfile(chan, prefile, chan->language) > -1)
- silent = ast_waitstream(chan, "#0");
+ res = ast_waitstream(chan, "#0");
} else {
ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
- silent = invent_message(chan, ext, busy, ecodes);
+ res = invent_message(chan, vmu->context, ext, busy, ecodes);
}
- if (silent < 0) {
+ if (res < 0) {
ast_log(LOG_DEBUG, "Hang up during prefile playback\n");
- free(copy);
+ free_user(vmu);
return -1;
}
}
- /* If they hit "#" we should still play the beep sound */
- if (silent == '#') {
- if (!ast_streamfile(chan, "beep", chan->language) < 0)
+ 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 == '#') {
silent = 1;
- if (ast_waitstream(chan, "") <0) {
- ast_log(LOG_DEBUG, "Hangup during beep\n");
- free(copy);
- return -1;
+ res = 0;
}
- } else if (silent == '0') {
+ }
+ /* Check for a '0' here */
+ if (res == '0') {
strncpy(chan->exten, "o", sizeof(chan->exten) - 1);
if (strlen(chan->macrocontext))
strncpy(chan->context, chan->macrocontext, sizeof(chan->context) - 1);
chan->priority = 0;
- free(copy);
+ free_user(vmu);
return 0;
}
- /* Stream an info message */
- if (silent || !ast_streamfile(chan, INTRO, chan->language)) {
- /* Wait for the message to finish */
- if (silent || !ast_waitstream(chan, "")) {
- if (!ast_streamfile(chan, "beep", chan->language) < 0)
- silent = 1;
- if (ast_waitstream(chan, "") <0) {
- ast_log(LOG_DEBUG, "Hangup during beep\n");
- free(copy);
- return -1;
- }
- fmt = ast_variable_retrieve(cfg, "general", "format");
- if (fmt) {
- char *stringp=NULL;
- fmts = strdup(fmt);
- stringp=fmts;
- fmt = strsep(&stringp, "|");
- 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"),
- name, ext, chan->name);
- if (ast_fileexists(fn, NULL, chan->language) > 0) {
- msgnum++;
- continue;
- }
- writer = ast_writefile(fn, fmt, comment, O_EXCL, 1 /* check for other formats */, 0700);
- if (!writer)
- break;
- msgnum++;
- } while(!writer && (msgnum < MAXMSG));
- if (writer) {
- char *stringp=NULL;
- /* Store information */
- snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
- txt = fopen(txtfile, "w+");
- if (txt) {
- get_date(date, sizeof(date));
- time(&start);
- fprintf(txt,
+ 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,
";\n"
"; Message Information file\n"
";\n"
@@ -643,198 +1198,44 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
chan->priority,
chan->name,
chan->callerid ? chan->callerid : "Unknown",
- date, (long) time(NULL));
- fclose(txt);
- } else
- ast_log(LOG_WARNING, "Error opening text file for output\n");
-
- /* We need to reset these values */
- free(fmts);
- fmt = ast_variable_retrieve(cfg, "general", "format");
- fmts = strdup(fmt);
- stringp=fmts;
- strsep(&stringp, "|");
- 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++] = strdup(fmt);
- }
- for (x=0;x<fmtcnt;x++) {
- others[x] = ast_writefile(fn, sfmt[x], comment, 0, 0, 0700);
- if (!others[x]) {
- /* Ick, the other format didn't work, but be sure not
- to leak memory here */
- int y;
- for(y=x+1;y < fmtcnt;y++)
- free(sfmt[y]);
- break;
- }
- if(!strcasecmp(sfmt[x], "wav"))
- wavother++;
- free(sfmt[x]);
- }
-
- sildet = ast_dsp_new(); //Create the silence detector
- if (silence > 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 (!sildet) {
- ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
- return -1;
- }
- ast_dsp_set_threshold(sildet, 50);
- }
-
- if (x == fmtcnt) {
- /* Loop forever, writing the packets we read to the writer(s), until
- we read a # or get a hangup */
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Recording to %s\n", fn);
- 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 the primary format */
- res = ast_writestream(writer, f);
- if (res) {
- ast_log(LOG_WARNING, "Error writing primary frame\n");
- break;
- }
- /* And each of the others */
- for (x=0;x<fmtcnt;x++) {
- res |= ast_writestream(others[x], f);
- }
- /* Exit on any error */
- if (res) {
- ast_log(LOG_WARNING, "Error writing frame\n");
- ast_frfree(f);
- break;
- }
- /* Silence Detection */
- if (silence > 0) {
- dspsilence = 0;
- ast_dsp_silence(sildet, f, &dspsilence);
- if (dspsilence) {
- totalsilence = dspsilence;
- } else {
- totalsilence = 0;
- }
- if (totalsilence > silence) {
- /* Ended happily with silence */
- outmsg=2;
- ast_frfree(f);
- gotsilence = 1;
- res = 0;
- break;
- }
- }
-
- } 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);
- outmsg=2;
- ast_frfree(f);
- res = 0;
- break;
- }
- }
- ast_frfree(f);
- time(&end);
- if (maxmessage && (end - start > maxmessage)) {
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Message is too long, ending it now...\n");
- outmsg = 2;
- res = 0;
- break;
- }
- }
- if (!f) {
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
- res = -1;
- outmsg=1;
- }
- if (gotsilence) {
- ast_stream_rewind(writer, silence-1000);
- ast_truncstream(writer);
-
- /* And each of the others */
- for (x=0;x<fmtcnt;x++) {
- ast_stream_rewind(others[x], silence-1000);
- ast_truncstream(others[x]);
- }
- }
- } else {
- ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", fn, sfmt[x]);
- free(sfmt[x]);
- }
-
- ast_closestream(writer);
- for (x=0;x<fmtcnt;x++) {
- if (!others[x])
- break;
- ast_closestream(others[x]);
- }
- if (outmsg) {
- if (outmsg > 1) {
- /* Let them know it worked */
- ast_streamfile(chan, "vm-msgsaved", chan->language);
- ast_waitstream(chan, "");
- }
- txt = fopen(txtfile, "a");
- if (txt) {
- time(&end);
- fprintf(txt, "duration=%ld\n", (long)(end-start));
- fclose(txt);
- }
- /* Send e-mail if applicable */
- if (email)
- sendmail(astemail, email, name, msgnum, ext, chan->callerid, fn, wavother ? "wav" : fmts, end - start);
- if (pager)
- sendpage(astemail, pager, msgnum, ext, chan->callerid, end - start);
- }
- } else {
- if (msgnum < MAXMSG)
- ast_log(LOG_WARNING, "Error writing to mailbox %s\n", ext);
- else
- ast_log(LOG_WARNING, "Too many messages in mailbox %s\n", ext);
- }
- free(fmts);
- } else
- ast_log(LOG_WARNING, "No format to save messages in \n");
- }
+ 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");
} else
- ast_log(LOG_WARNING, "Unable to playback instructions\n");
-
- free(copy);
+ ast_log(LOG_WARNING, "No format for saving voicemail?\n");
+ free_user(vmu);
} else
ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
- ast_destroy(cfg);
/* Leave voicemail for someone */
manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext, ast_app_has_voicemail(ext));
return res;
@@ -880,16 +1281,6 @@ static int count_messages(char *dir)
return x;
}
-static int play_and_wait(struct ast_channel *chan, char *fn)
-{
- int d;
- d = ast_streamfile(chan, fn, chan->language);
- if (d)
- return d;
- d = ast_waitstream(chan, AST_DIGIT_ANY);
- return d;
-}
-
static int say_and_wait(struct ast_channel *chan, int num)
{
int d;
@@ -936,7 +1327,7 @@ static int copy(char *infile, char *outfile)
return 0;
}
-static int save_to_folder(char *dir, int msg, char *username, int box)
+static int save_to_folder(char *dir, int msg, char *context, char *username, int box)
{
char sfn[256];
char dfn[256];
@@ -946,7 +1337,7 @@ static int save_to_folder(char *dir, int msg, char *username, int box)
char *dbox = mbox(box);
int x;
make_file(sfn, sizeof(sfn), dir, msg);
- make_dir(ddir, sizeof(ddir), username, dbox);
+ make_dir(ddir, sizeof(ddir), context, username, dbox);
mkdir(ddir, 0700);
for (x=0;x<MAXMSG;x++) {
make_file(dfn, sizeof(dfn), ddir, x);
@@ -1016,7 +1407,7 @@ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
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);
- bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "4", 1);
+ bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
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);
@@ -1025,6 +1416,8 @@ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
/* Add another dot */
bytes = 0;
bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
+ bytes += adsi_voice_mode(buf + bytes, 0);
+
bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
#endif
@@ -1074,6 +1467,7 @@ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
}
bytes = 0;
bytes += adsi_download_disconnect(buf + bytes);
+ bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
ast_log(LOG_DEBUG, "Done downloading scripts...\n");
@@ -1159,6 +1553,7 @@ static void adsi_password(struct ast_channel *chan)
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);
+ bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
}
@@ -1186,6 +1581,8 @@ static void adsi_folders(struct ast_channel *chan, int start, char *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);
+ bytes += adsi_voice_mode(buf + bytes, 0);
+
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
}
@@ -1194,6 +1591,7 @@ static void adsi_message(struct ast_channel *chan, char *folder, int msg, int la
int bytes=0;
char buf[256], buf1[256], buf2[256];
char fn2[256];
+
char cid[256]="";
char *val;
char *name, *num;
@@ -1243,6 +1641,8 @@ static void adsi_message(struct ast_channel *chan, char *folder, int msg, int la
if (msg) {
/* but not only message, provide "Folder" instead */
keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
+ bytes += adsi_voice_mode(buf + bytes, 0);
+
} else {
/* Otherwise if only message, leave blank */
keys[3] = 1;
@@ -1257,6 +1657,7 @@ static void adsi_message(struct ast_channel *chan, char *folder, int msg, int la
name = "Unknown Caller";
/* If deleted, show "undeleted" */
+
if (deleted)
keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
@@ -1272,6 +1673,8 @@ static void adsi_message(struct ast_channel *chan, char *folder, int msg, int la
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);
+ bytes += adsi_voice_mode(buf + bytes, 0);
+
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
}
@@ -1315,6 +1718,8 @@ static void adsi_delete(struct ast_channel *chan, int msg, int last, int deleted
/* Except "Exit" */
keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
bytes += adsi_set_keys(buf + bytes, keys);
+ bytes += adsi_voice_mode(buf + bytes, 0);
+
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
}
@@ -1358,6 +1763,8 @@ static void adsi_status(struct ast_channel *chan, int new, int old, int lastmsg)
keys[0] = 1;
bytes += adsi_set_keys(buf + bytes, keys);
+ bytes += adsi_voice_mode(buf + bytes, 0);
+
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
}
@@ -1396,6 +1803,8 @@ static void adsi_status2(struct ast_channel *chan, char *folder, int messages)
bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
bytes += adsi_set_keys(buf + bytes, keys);
+ bytes += adsi_voice_mode(buf + bytes, 0);
+
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
}
@@ -1407,6 +1816,8 @@ static void adsi_clear(struct ast_channel *chan)
if (!adsi_available(chan))
return;
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);
}
@@ -1421,6 +1832,8 @@ static void adsi_goodbye(struct ast_channel *chan)
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);
+ bytes += adsi_voice_mode(buf + bytes, 0);
+
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
}
@@ -1456,8 +1869,19 @@ static int get_folder(struct ast_channel *chan, int start)
return d;
}
+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;
+}
+
static int
-forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int curmsg, char* myusername)
+forward_message(struct ast_channel *chan, char *context, char *dir, int curmsg, struct ast_vm_user *sender, char *fmt)
{
char username[70];
char sys[256];
@@ -1466,341 +1890,435 @@ forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int
long duration;
struct ast_config *mif;
char miffile[256];
- char *copy, *name, *passwd, *email, *pager;
- char *mycopy, *myname, *mypasswd, *myemail, *mypager;
- char *astemail;
char fn[256];
char callerid[512];
+ int res = 0;
+ struct ast_vm_user *receiver, srec;
+ char tmp[256];
+ char *stringp, *s;
- while(1) {
- ast_streamfile(chan, "vm-extension", chan->language);
-
- if (ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0)
- return 0;
- if (ast_variable_retrieve(cfg, NULL, username)) {
- printf("Got %d\n", atoi(username));
+ while(!res) {
+ res = ast_streamfile(chan, "vm-extension", chan->language);
+ if (res)
+ break;
+ if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
+ break;
+ if ((receiver = find_user(&srec, context, username))) {
/* if (play_and_wait(chan, "vm-savedto"))
break;
*/
- snprintf(todir, sizeof(todir), "%s/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR,"vm", username);
+ snprintf(todir, sizeof(todir), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, receiver->context, username);
snprintf(sys, sizeof(sys), "mkdir -p %s\n", todir);
- puts(sys);
+ ast_log(LOG_DEBUG, sys);
system(sys);
todircount = count_messages(todir);
-
- snprintf(sys, sizeof(sys), "cp %s/msg%04d.gsm %s/msg%04d.gsm\n", dir, curmsg, todir, todircount);
- puts(sys);
- system(sys);
-
- /* TODO: use config to determine what other formats to copy the message in */
- snprintf(sys, sizeof(sys), "cp %s/msg%04d.wav %s/msg%04d.wav\n", dir, curmsg, todir, todircount);
- puts(sys);
- system(sys);
-
- /* copy the message information file too */
+ strncpy(tmp, fmt, sizeof(tmp));
+ stringp = tmp;
+ while((s = strsep(&stringp, "|"))) {
+ snprintf(sys, sizeof(sys), "cp %s/msg%04d.%s %s/msg%04d.%s\n", dir, curmsg, s, todir, todircount, s);
+ ast_log(LOG_DEBUG, sys);
+ system(sys);
+ }
snprintf(sys, sizeof(sys), "cp %s/msg%04d.txt %s/msg%04d.txt\n", dir, curmsg, todir, todircount);
- puts(sys);
+ 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))) {
- /* send an e-mail like it was a new message if appropriate */
- if ((copy = ast_variable_retrieve(cfg, NULL, username))) {
- char *stringp=NULL;
- /* Make sure they have an entry in the config */
- copy = strdup(copy);
- stringp=copy;
- passwd = strsep(&stringp, ",");
- name = strsep(&stringp, ",");
- email = strsep(&stringp, ",");
- pager = strsep(&stringp, ",");
- }
-
- if ((mycopy = ast_variable_retrieve(cfg, NULL, myusername))) {
- char *mystringp=NULL;
- /* Make sure they have an entry in the config */
- mycopy = strdup(mycopy);
- mystringp=mycopy;
- mypasswd = strsep(&mystringp, ",");
- myname = strsep(&mystringp, ",");
- myemail = strsep(&mystringp, ",");
- mypager = strsep(&mystringp, ",");
- }
-
- /* set the outbound email from address */
- if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail")))
- astemail = ASTERISK_USERNAME;
-
/* set callerid and duration variables */
- snprintf(callerid, sizeof(callerid), "FWD from: %s from %s", myname, ast_variable_retrieve(mif, NULL, "callerid"));
+ snprintf(callerid, sizeof(callerid), "FWD from: %s from %s", sender->fullname, ast_variable_retrieve(mif, NULL, "callerid"));
duration = atol(ast_variable_retrieve(mif, NULL, "duration"));
- if (email)
- sendmail(astemail, email, name, todircount, username, callerid, fn, "wav", atol(ast_variable_retrieve(mif, NULL, "duration")));
-
- if (pager)
- sendpage(astemail, pager, todircount, username, callerid, duration);
+ if (strlen(receiver->email)) {
+ int attach_user_voicemail = attach_voicemail;
+ char *myserveremail = serveremail;
+ if (receiver->attach > -1)
+ attach_user_voicemail = receiver->attach;
+ if (strlen(receiver->serveremail))
+ myserveremail = receiver->serveremail;
+ sendmail(myserveremail, receiver, todircount, username, callerid, fn, tmp, atol(ast_variable_retrieve(mif, NULL, "duration")), attach_user_voicemail);
+ }
+
+ if (strlen(receiver->pager)) {
+ char *myserveremail = serveremail;
+ if (strlen(receiver->serveremail))
+ myserveremail = receiver->serveremail;
+ sendpage(myserveremail, receiver->pager, todircount, username, callerid, duration, receiver);
+ }
- free(copy); /* no leaks here */
- free(mycopy); /* or here */
ast_destroy(mif); /* or here */
}
+ /* Leave voicemail for someone */
+ manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", username, ast_app_has_voicemail(username));
/* give confirmatopm that the message was saved */
- if (play_and_wait(chan, "vm-message")) break;
- if (play_and_wait(chan, "vm-saved")) break;
-
+ res = play_and_wait(chan, "vm-message");
+ if (!res)
+ res = play_and_wait(chan, "vm-saved");
+ free_user(receiver);
break;
} else {
- if ( play_and_wait(chan, "pbx-invalid"))
- break;
+ res = play_and_wait(chan, "pbx-invalid");
}
}
- return 0;
+ return res;
}
-#define WAITCMD(a) do { \
- d = (a); \
- if (d < 0) \
- goto out; \
- if (d) \
- goto cmd; \
-} while(0)
-
-#define WAITFILE2(file) do { \
- if (ast_streamfile(chan, file, chan->language)) \
- ast_log(LOG_WARNING, "Unable to play message %s\n", file); \
- d = ast_waitstream(chan, AST_DIGIT_ANY); \
- if (d < 0) { \
- goto out; \
- }\
-} while(0)
-
-#define WAITFILE(file) do { \
- if (ast_streamfile(chan, file, chan->language)) \
- ast_log(LOG_WARNING, "Unable to play message %s\n", file); \
- if ((s = ast_variable_retrieve(cfg, "general", "skipms"))) { \
- if (sscanf(s, "%d", &x) == 1) \
- ms = x; \
- } \
- d = ast_waitstream_fr(chan, AST_DIGIT_ANY, "#", "*",ms); \
- if (!d) { \
- repeats = 0; \
- goto instructions; \
- } else if (d < 0) { \
- goto out; \
- } else goto cmd;\
-} while(0)
-
-#define PLAYMSG(a) do { \
- starting = 0; \
- make_file(fn, sizeof(fn), curdir, a); \
- adsi_message(chan, curbox, a, lastmsg, deleted[a], fn); \
- if (!a) \
- WAITFILE2("vm-first"); \
- else if (a == lastmsg) \
- WAITFILE2("vm-last"); \
- WAITFILE2("vm-message"); \
- if (a && (a != lastmsg)) { \
- d = ast_say_number(chan, a + 1, AST_DIGIT_ANY, chan->language); \
- if (d < 0) goto out; \
- if (d) goto cmd; \
- } \
- make_file(fn, sizeof(fn), curdir, a); \
- heard[a] = 1; \
- WAITFILE(fn); \
-} while(0)
-
-#define CLOSE_MAILBOX do { \
- if (lastmsg > -1) { \
- /* Get the deleted messages fixed */ \
- curmsg = -1; \
- for (x=0;x<=lastmsg;x++) { \
- if (!deleted[x] && (strcasecmp(curbox, "INBOX") || !heard[x])) { \
- /* Save this message. It's not in INBOX or hasn't been heard */ \
- curmsg++; \
- make_file(fn, sizeof(fn), curdir, x); \
- make_file(fn2, sizeof(fn2), curdir, curmsg); \
- if (strcmp(fn, fn2)) { \
- snprintf(txt, sizeof(txt), "%s.txt", fn); \
- snprintf(ntxt, sizeof(ntxt), "%s.txt", fn2); \
- ast_filerename(fn, fn2, NULL); \
- rename(txt, ntxt); \
- } \
- } else if (!strcasecmp(curbox, "INBOX") && heard[x] && !deleted[x]) { \
- /* Move to old folder before deleting */ \
- save_to_folder(curdir, x, username, 1); \
- } \
- } \
- for (x = curmsg + 1; x<=lastmsg; x++) { \
- make_file(fn, sizeof(fn), curdir, x); \
- snprintf(txt, sizeof(txt), "%s.txt", fn); \
- ast_filedelete(fn, NULL); \
- unlink(txt); \
- } \
- } \
- memset(deleted, 0, sizeof(deleted)); \
- memset(heard, 0, sizeof(heard)); \
-} while(0)
-
-#define OPEN_MAILBOX(a) do { \
- strcpy(curbox, mbox(a)); \
- make_dir(curdir, sizeof(curdir), username, curbox); \
- lastmsg = count_messages(curdir) - 1; \
- snprintf(vmbox, sizeof(vmbox), "vm-%s", curbox); \
-} while (0)
-
-static int play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime)
+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;
+};
+
+
+static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
{
- char d, *fmt, *fmts;
- char comment[256];
- int x, fmtcnt=1, res=-1,outmsg=0, wavother=0;
- struct ast_frame *f;
- struct ast_config *cfg;
- struct ast_filestream *others[MAX_OTHER_FORMATS];
- char *sfmt[MAX_OTHER_FORMATS];
- char *stringp=NULL;
- time_t start, end;
-
-
- ast_log(LOG_DEBUG,"play_and_record: %s, %s\n", playfile, recordfile);
- snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile, recordfile, chan->name);
-
- d = play_and_wait(chan, playfile);
- if (d < 0)
- return -1;
- ast_streamfile(chan, "beep",chan->language);
- ast_waitstream(chan,"");
- cfg = ast_load(VOICEMAIL_CONFIG);
-
- fmt = ast_variable_retrieve(cfg, "general", "format");
- ast_log(LOG_DEBUG,"Recording Formats: fmt=%s\n", fmt);
-
- fmts = strdup(fmt);
-
- ast_destroy(cfg);
+ 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;
+}
- stringp=fmts;
- strsep(&stringp, "|");
- ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
- sfmt[0] = strdup(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;
+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;
}
- sfmt[fmtcnt++] = strdup(fmt);
+ z = z->next;
}
+ }
- 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\n", x, recordfile, sfmt[x]);
-
- if (!others[x]) {
- /* Ick, the other format didn't work, but be sure not
- to leak memory here */
- int y;
- for(y=x+1;y < fmtcnt;y++)
- free(sfmt[y]);
- break;
- }
- if(!strcasecmp(sfmt[x], "wav"))
- wavother++;
- free(sfmt[x]);
- }
- 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;
- }
+/* 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);
- 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);
- }
- /* Exit on any error */
- if (res) {
- ast_log(LOG_WARNING, "Error writing frame\n");
- ast_frfree(f);
- break;
- }
- } 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);
- outmsg=2;
- 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");
- outmsg=2;
- 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]);
- free(sfmt[x]);
- }
+ /* 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;
+}
- for (x=0;x<fmtcnt;x++) {
- if (!others[x])
+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)
break;
- ast_closestream(others[x]);
- }
- if (outmsg) {
- if (outmsg > 1) {
- /* Let them know it worked */
- ast_streamfile(chan, "vm-msgsaved", chan->language);
- ast_waitstream(chan, "");
- }
- }
+ 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));
+}
-
- return 0;
+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;
+}
+
+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;
}
+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;
+ 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;
+}
static int vm_execmain(struct ast_channel *chan, void *data)
{
@@ -1810,57 +2328,28 @@ static int vm_execmain(struct ast_channel *chan, void *data)
int res=-1;
int valid = 0;
int prefix = 0;
- char d;
+ int cmd=0;
struct localuser *u;
- char username[80] ="";
char prefixstr[80] ="";
char empty[80] = "";
- char password[80] = "", *copy;
- char newpassword[80] = "";
- char newpassword2[80] = "";
- char curbox[80] = "";
- char curdir[256] = "";
- char vmbox[256] = "";
- char fn[256] = "";
- char fn2[256] = "";
- char prefile[256]="";
- int x;
- char ntxt[256] = "";
- char txt[256] = "";
- int deleted[MAXMSG] = { 0, };
- int heard[MAXMSG] = { 0, };
- int newmessages;
- int oldmessages;
- int repeats = 0;
- int curmsg = 0;
- int lastmsg = 0;
- int starting = 1;
int box;
int useadsi = 0;
int skipuser = 0;
- char *s;
- int ms = 3000;
- int maxgreet = 0;
char tmp[256], *ext;
- struct ast_config *cfg;
+ char fmtc[256] = "";
+ char password[80];
+ struct vm_state vms;
+ int logretries = 0;
+ struct ast_vm_user *vmu = NULL, vmus;
+ char *context=NULL;
LOCAL_USER_ADD(u);
- cfg = ast_load(VOICEMAIL_CONFIG);
- if (!cfg) {
- ast_log(LOG_WARNING, "No voicemail configuration\n");
- goto out;
- }
- 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");
- }
- }
+ memset(&vms, 0, sizeof(vms));
+ strncpy(fmtc, vmfmts, sizeof(fmtc) - 1);
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
- if (strlen(data)) {
+ if (data && strlen(data)) {
strncpy(tmp, data, sizeof(tmp) - 1);
ext = tmp;
@@ -1877,13 +2366,17 @@ static int vm_execmain(struct ast_channel *chan, void *data)
break;
}
+ context = strchr(ext, '@');
+ if (context) {
+ *context = '\0';
+ context++;
+ }
if (prefix)
strncpy(prefixstr, ext, sizeof(prefixstr) - 1);
else
- strncpy(username, ext, sizeof(username) - 1);
- /* make sure username passed as an option is valid */
- if (ast_variable_retrieve(cfg, NULL, username))
+ strncpy(vms.username, ext, sizeof(vms.username) - 1);
+ if (strlen(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
skipuser++;
else
valid = 0;
@@ -1901,13 +2394,13 @@ static int vm_execmain(struct ast_channel *chan, void *data)
/* Authenticate them and get their mailbox/password */
- while (!valid) {
+ while (!valid && (logretries < maxlogins)) {
/* Prompt for, and read in the username */
- if (!skipuser && ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0) {
+ if (!skipuser && ast_readstring(chan, vms.username, sizeof(vms.username) - 1, 2000, 10000, "#") < 0) {
ast_log(LOG_WARNING, "Couldn't read username\n");
goto out;
}
- if (!strlen(username)) {
+ if (!strlen(vms.username)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Username not entered\n");
res = 0;
@@ -1926,311 +2419,212 @@ static int vm_execmain(struct ast_channel *chan, void *data)
if (prefix) {
char fullusername[80] = "";
strncpy(fullusername, prefixstr, sizeof(fullusername) - 1);
- strncat(fullusername, username, sizeof(fullusername) - 1);
- strncpy(username, fullusername, sizeof(username) - 1);
- }
- copy = ast_variable_retrieve(cfg, NULL, username);
- if (copy) {
- char *stringp=NULL;
- copy = strdup(copy);
- stringp=copy;
- strsep(&stringp, ",");
- if (!strcmp(password,copy))
- valid++;
- else {
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Incorrect password '%s' for user '%s'\n", password, username);
- if (prefix)
- strncpy(username, empty, sizeof(username) -1);
- }
- free(copy);
- } else {
- skipuser = 0;
+ 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 {
if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "No such user '%s' in config file\n", username);
+ 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);
}
if (!valid) {
if (useadsi)
adsi_login(chan);
if (ast_streamfile(chan, "vm-incorrect", chan->language))
break;
-#if 0
- if (ast_waitstream(chan, ""))
- break;
-#endif
}
+ logretries++;
+ }
+ if (!valid && (logretries >= maxlogins)) {
+ ast_stopstream(chan);
+ res = play_and_wait(chan, "vm-goodbye");
+ if (res > 0)
+ res = 0;
}
if (valid) {
- snprintf(curdir, sizeof(curdir), "%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR,"vm", username);
- mkdir(curdir, 0700);
- OPEN_MAILBOX(1);
- oldmessages = lastmsg + 1;
+ 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;
/* Start in INBOX */
- OPEN_MAILBOX(0);
- newmessages = lastmsg + 1;
+ open_mailbox(&vms, vmu, 0);
+ vms.newmessages = vms.lastmsg + 1;
/* Select proper mailbox FIRST!! */
- if (!newmessages && oldmessages) {
+ if (!vms.newmessages && vms.oldmessages) {
/* If we only have old messages start here */
- OPEN_MAILBOX(1);
+ open_mailbox(&vms, vmu, 1);
}
if (useadsi)
- adsi_status(chan, newmessages, oldmessages, lastmsg);
-
- WAITCMD(play_and_wait(chan, "vm-youhave"));
- if (newmessages) {
- WAITCMD(say_and_wait(chan, newmessages));
- WAITCMD(play_and_wait(chan, "vm-INBOX"));
-
- if (oldmessages)
- WAITCMD(play_and_wait(chan, "vm-and"));
- else {
- if (newmessages == 1)
- WAITCMD(play_and_wait(chan, "vm-message"));
+ 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");
else
- WAITCMD(play_and_wait(chan, "vm-messages"));
- }
-
- }
- if (oldmessages) {
- WAITCMD(say_and_wait(chan, oldmessages));
- WAITCMD(play_and_wait(chan, "vm-Old"));
- if (oldmessages == 1)
- WAITCMD(play_and_wait(chan, "vm-message"));
- else
- WAITCMD(play_and_wait(chan, "vm-messages"));
- }
- if (!oldmessages && !newmessages) {
- WAITCMD(play_and_wait(chan, "vm-no"));
- WAITCMD(play_and_wait(chan, "vm-messages"));
- }
- repeats = 0;
- starting = 1;
-instructions:
- if (starting) {
- if (lastmsg > -1) {
- WAITCMD(play_and_wait(chan, "vm-onefor"));
- WAITCMD(play_and_wait(chan, vmbox));
- WAITCMD(play_and_wait(chan, "vm-messages"));
- }
- WAITCMD(play_and_wait(chan, "vm-opts"));
- } else {
- if (curmsg)
- WAITCMD(play_and_wait(chan, "vm-prev"));
- WAITCMD(play_and_wait(chan, "vm-repeat"));
- if (curmsg != lastmsg)
- WAITCMD(play_and_wait(chan, "vm-next"));
- if (!deleted[curmsg])
- WAITCMD(play_and_wait(chan, "vm-delete"));
- else
- WAITCMD(play_and_wait(chan, "vm-undelete"));
- WAITCMD(play_and_wait(chan, "vm-toforward"));
- WAITCMD(play_and_wait(chan, "vm-savemessage"));
- }
- WAITCMD(play_and_wait(chan, "vm-helpexit"));
- d = ast_waitfordigit(chan, 6000);
- if (d < 0)
- goto out;
- if (!d) {
- repeats++;
- if (repeats > 2) {
- play_and_wait(chan, "vm-goodbye");
- goto out;
+ 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;
}
- goto instructions;
}
-cmd:
- switch(d) {
- case '2':
- if (useadsi)
- adsi_folders(chan, 0, "Change to folder...");
- box = play_and_wait(chan, "vm-changeto");
- if (box < 0)
- goto out;
- while((box < '0') || (box > '9')) {
- box = get_folder(chan, 0);
- if (box < 0)
- goto out;
- if (box == '#')
- goto instructions;
- }
- box = box - '0';
- CLOSE_MAILBOX;
- OPEN_MAILBOX(box);
- if (useadsi)
- adsi_status2(chan, curbox, lastmsg + 1);
- WAITCMD(play_and_wait(chan, vmbox));
- WAITCMD(play_and_wait(chan, "vm-messages"));
- starting = 1;
- goto instructions;
- case '4':
- if (curmsg) {
- curmsg--;
- PLAYMSG(curmsg);
- } else {
- WAITCMD(play_and_wait(chan, "vm-nomore"));
- goto instructions;
- }
- case '1':
- curmsg = 0;
- /* Fall through */
- case '5':
- if (lastmsg > -1) {
- PLAYMSG(curmsg);
- } else {
- WAITCMD(play_and_wait(chan, "vm-youhave"));
- WAITCMD(play_and_wait(chan, "vm-no"));
- snprintf(fn, sizeof(fn), "vm-%s", curbox);
- WAITCMD(play_and_wait(chan, fn));
- WAITCMD(play_and_wait(chan, "vm-messages"));
- goto instructions;
- }
- case '6':
- if (curmsg < lastmsg) {
- curmsg++;
- PLAYMSG(curmsg);
- } else {
- WAITCMD(play_and_wait(chan, "vm-nomore"));
- goto instructions;
- }
- case '7':
- deleted[curmsg] = !deleted[curmsg];
- if (useadsi)
- adsi_delete(chan, curmsg, lastmsg, deleted[curmsg]);
- if (deleted[curmsg])
- WAITCMD(play_and_wait(chan, "vm-deleted"));
- else
- WAITCMD(play_and_wait(chan, "vm-undeleted"));
- goto instructions;
- case '8':
- if(lastmsg > -1)
- if(forward_message(chan, cfg, curdir, curmsg, username) < 0)
- goto out;
- goto instructions;
- case '9':
- if (useadsi)
- adsi_folders(chan, 1, "Save to folder...");
- box = play_and_wait(chan, "vm-savefolder");
- if (box < 0)
- goto out;
- while((box < '1') || (box > '9')) {
- box = get_folder(chan, 1);
- if (box < 0)
- goto out;
- if (box == '#')
- goto instructions;
- }
- box = box - '0';
- if (option_debug)
- ast_log(LOG_DEBUG, "Save to folder: %s (%d)\n", mbox(box), box);
- if (save_to_folder(curdir, curmsg, username, box))
- goto out;
- deleted[curmsg]=1;
- make_file(fn, sizeof(fn), curdir, curmsg);
- if (useadsi)
- adsi_message(chan, curbox, curmsg, lastmsg, deleted[curmsg], fn);
- WAITCMD(play_and_wait(chan, "vm-message"));
- WAITCMD(say_and_wait(chan, curmsg + 1) );
- WAITCMD(play_and_wait(chan, "vm-savedto"));
- snprintf(fn, sizeof(fn), "vm-%s", mbox(box));
- WAITCMD(play_and_wait(chan, fn));
- WAITCMD(play_and_wait(chan, "vm-messages"));
- goto instructions;
- case '*':
- if (!starting) {
- WAITCMD(play_and_wait(chan, "vm-onefor"));
- WAITCMD(play_and_wait(chan, vmbox));
- WAITCMD(play_and_wait(chan, "vm-messages"));
- WAITCMD(play_and_wait(chan, "vm-opts"));
- }
- goto instructions;
- case '#':
- ast_stopstream(chan);
- adsi_goodbye(chan);
- play_and_wait(chan, "vm-goodbye");
+ if ((cmd == 't') || (cmd == '#')) {
+ /* Timeout */
res = 0;
- goto out2;
-
- case '0':
- goto vm_options;
-
- default:
- goto instructions;
+ } else {
+ /* Hangup */
+ res = -1;
}
}
out:
- adsi_goodbye(chan);
-out2:
- CLOSE_MAILBOX;
- ast_stopstream(chan);
- if (cfg)
- ast_destroy(cfg);
- if (useadsi)
- adsi_unload_session(chan);
+ 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);
if (valid) {
- manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", username, ast_app_has_voicemail(username));
+ manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", vms.username, ast_app_has_voicemail(vms.username));
}
LOCAL_USER_REMOVE(u);
return res;
-vm_options:
- d = play_and_wait(chan,"vm-options");
- if (!d)
- d = ast_waitfordigit(chan,6000);
- if (d < 0)
- goto out;
- switch (d) {
-
- case '1':
- snprintf(prefile,sizeof(prefile),"vm/%s/unavail",username);
- play_and_record(chan,"vm-rec-unv",prefile, maxgreet);
- break;
- case '2':
- snprintf(prefile,sizeof(prefile),"vm/%s/busy",username);
- play_and_record(chan,"vm-rec-busy",prefile, maxgreet);
- break;
- case '3':
- snprintf(prefile,sizeof(prefile),"vm/%s/greet",username);
- play_and_record(chan,"vm-rec-name",prefile, maxgreet);
- break;
- case '4':
- newpassword[1] = '\0';
- newpassword[0] = play_and_wait(chan,"vm-newpassword");
- if (ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#") < 0) {
- play_and_wait(chan, "vm-sorry");
- ast_log(LOG_NOTICE,"Unable to read new password\n");
- goto vm_options;
- }
- newpassword2[1] = '\0';
- newpassword2[0] = play_and_wait(chan,"vm-reenterpassword");
-
- if (ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#") < 0) {
- play_and_wait(chan, "vm-sorry");
- ast_log(LOG_NOTICE,"Unable to read re-entered password\n");
- goto vm_options;
- }
- if (strcmp(newpassword, newpassword2)) {
- ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", username, newpassword, newpassword2);
- play_and_wait(chan, "vm-mismatch");
- goto vm_options;
- }
- if (vm_change_password(username,password,newpassword) < 0)
- {
- ast_log(LOG_DEBUG,"Failed to set new password of user %s\n",username);
- } else
- ast_log(LOG_DEBUG,"User %s set password to %s of length %i\n",username,newpassword,strlen(newpassword));
- play_and_wait(chan,"vm-passchanged");
- break;
- case '*':
- goto instructions;
-
- default:
- goto vm_options;
- }
- goto vm_options;
}
static int vm_exec(struct ast_channel *chan, void *data)
@@ -2252,27 +2646,287 @@ static int vm_exec(struct ast_channel *chan, void *data)
return 0;
}
ext = tmp;
- if (*ext == 's') {
- silent++;
- ext++;
- } else if (*ext == 'b') {
- busy++;
- ext++;
- } else if (*ext == 'u') {
- unavail++;
- ext++;
+ while(*ext) {
+ if (*ext == 's') {
+ silent = 2;
+ ext++;
+ } else if (*ext == 'b') {
+ busy=1;
+ ext++;
+ } else if (*ext == 'u') {
+ unavail=1;
+ ext++;
+ } else
+ break;
}
res = leave_voicemail(chan, ext, silent, busy, unavail);
LOCAL_USER_REMOVE(u);
return res;
}
+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());
+}
+
int unload_module(void)
{
int res;
STANDARD_HANGUP_LOCALUSERS;
res = ast_unregister_application(app);
res |= ast_unregister_application(app2);
+ sql_close();
return res;
}
@@ -2280,8 +2934,20 @@ int load_module(void)
{
int res;
res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
- if (!res)
- res = ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
+ 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;
+ }
return res;
}
diff --git a/apps/app_voicemail2.c b/apps/app_voicemail2.c
deleted file mode 100755
index 66699f9e4..000000000
--- a/apps/app_voicemail2.c
+++ /dev/null
@@ -1,2965 +0,0 @@
-/*
- * Asterisk -- A telephony toolkit for Linux.
- *
- * Voicemail System (did you ever think it could be so easy?)
- *
- * Copyright (C) 1999, Mark Spencer
- *
- * Mark Spencer <markster@linux-support.net>
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License
- */
-
-#include <asterisk/lock.h>
-#include <asterisk/file.h>
-#include <asterisk/logger.h>
-#include <asterisk/channel.h>
-#include <asterisk/channel_pvt.h>
-#include <asterisk/pbx.h>
-#include <asterisk/options.h>
-#include <asterisk/config.h>
-#include <asterisk/say.h>
-#include <asterisk/module.h>
-#include <asterisk/adsi.h>
-#include <asterisk/app.h>
-#include <asterisk/manager.h>
-#include <asterisk/dsp.h>
-#include <asterisk/localtime.h>
-#include <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>
-
-/* 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
-
-#include <pthread.h>
-#include "../asterisk.h"
-#include "../astconf.h"
-
-#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"
-
-#define BASEMAXINLINE 256
-#define BASELINELEN 72
-#define BASEMAXINLINE 256
-#define eol "\r\n"
-
-#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;
-};
-
-static char *tdesc = "Comedian Mail (Voicemail System)";
-
-static char *adapp = "CoMa";
-
-static char *adsec = "_AST";
-
-static char *addesc = "Comedian Mail";
-
-static int adver = 1;
-
-static char *synopsis_vm =
-"Leave a voicemail message";
-
-static char *descrip_vm =
-" 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"
-"Returns -1 on error or mailbox not found, or if the user hangs up.\n"
-"Otherwise, it returns 0.\n";
-
-static char *synopsis_vmain =
-"Enter voicemail system";
-
-static char *descrip_vmain =
-" 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";
-
-/* Leave a message */
-static char *app = "VoiceMail2";
-
-/* Check mail, control, etc */
-static char *app2 = "VoiceMailMain2";
-
-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];
-
-STANDARD_LOCAL_USER;
-
-LOCAL_USER_DECL;
-
-static void apply_options(struct ast_vm_user *vmu, char *options)
-{
- /* 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);
- }
- }
- }
-
-}
-
-#ifdef USEMYSQLVM
-#include "mysql-vm-routines.h"
-#endif
-
-#ifdef USEPOSTGRESVM
-
-PGconn *dbhandler;
-char dboption[256];
-ast_mutex_t postgreslock;
-
-static int sql_init(void)
-{
- 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);
- }
-
- if (*retval->context) {
- sprintf(query, "SELECT password,fullname,email,pager,options FROM voicemail WHERE context='%s' AND mailbox='%s'", context, mailbox);
- } else {
- sprintf(query, "SELECT password,fullname,email,pager,options FROM voicemail WHERE mailbox='%s'", mailbox);
- }
-/* 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;
-}
-
-static void vm_change_password(struct ast_vm_user *vmu, char *newpassword)
-{
- /* There's probably a better way of doing this. */
- /* That's why I've put the password change in a separate function. */
- /* This could also be done with a database function */
-
- FILE *configin;
- FILE *configout;
- char inbuf[256];
- char orig[256];
- char tmpin[AST_CONFIG_MAX_PATH];
- char tmpout[AST_CONFIG_MAX_PATH];
- char *user, *pass, *rest, *trim;
- 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);
- configin = fopen((char *)tmpin,"r");
- 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;
- }
-
- 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;
- if (user && pass && *user && *pass && !strcmp(user, vmu->mailbox) && !strcmp(pass, vmu->password)) {
- /* This is the line */
- if (rest) {
- fprintf(configout, "%s => %s,%s\n", vmu->mailbox,newpassword,rest);
- } else {
- fprintf(configout, "%s => %s\n", vmu->mailbox,newpassword);
- }
- } else {
- /* Put it back like it was */
- fprintf(configout, orig);
- }
- }
- }
- fclose(configin);
- fclose(configout);
-
- unlink((char *)tmpin);
- rename((char *)tmpout,(char *)tmpin);
- 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);
-}
-
-static int
-inbuf(struct baseio *bio, FILE *fi)
-{
- int l;
-
- if(bio->ateof)
- return 0;
-
- if ( (l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
- if(ferror(fi))
- return -1;
-
- bio->ateof = 1;
- return 0;
- }
-
- bio->iolen= l;
- bio->iocp= 0;
-
- return 1;
-}
-
-static int
-inchar(struct baseio *bio, FILE *fi)
-{
- if(bio->iocp>=bio->iolen)
- if(!inbuf(bio, fi))
- return EOF;
-
- return bio->iobuf[bio->iocp++];
-}
-
-static int
-ochar(struct baseio *bio, int c, FILE *so)
-{
- if(bio->linelength>=BASELINELEN) {
- if(fputs(eol,so)==EOF)
- return -1;
-
- bio->linelength= 0;
- }
-
- if(putc(((unsigned char)c),so)==EOF)
- return -1;
-
- bio->linelength++;
-
- return 1;
-}
-
-static int base_encode(char *filename, FILE *so)
-{
- unsigned char dtable[BASEMAXINLINE];
- int i,hiteof= 0;
- FILE *fi;
- struct baseio bio;
-
- memset(&bio, 0, sizeof(bio));
- bio.iocp = BASEMAXINLINE;
-
- 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++){
- if ( (c = inchar(&bio, fi)) == EOF) {
- 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++)
- ochar(&bio, ogroup[i], so);
- }
- }
-
- if(fputs(eol,so)==EOF)
- return 0;
-
- fclose(fi);
-
- return 1;
-}
-
-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)
-{
- FILE *p;
- char date[256];
- char host[256];
- char who[256];
- char bound[256];
- char fname[256];
- char dur[256];
- time_t t;
- struct tm tm;
- 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);
- 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);
-
- /* 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);
- strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
- fprintf(p, "Date: %s\n", date);
-
- 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);
- fprintf(p, "Message-ID: <Asterisk-%d-%s-%d@%s>\n", msgnum, mailbox, getpid(), host);
- fprintf(p, "MIME-Version: 1.0\n");
- if (attach_user_voicemail) {
- // Something unique.
- snprintf(bound, sizeof(bound), "Boundary=%d%s%d", msgnum, mailbox, getpid());
-
- fprintf(p, "Content-Type: MULTIPART/MIXED; BOUNDARY=\"%s\"\n\n\n", bound);
-
- fprintf(p, "--%s\n", bound);
- }
- 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 {
- fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message (number %d)\n"
-
- "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) {
- fprintf(p, "--%s\n", bound);
- fprintf(p, "Content-Type: audio/x-wav; name=\"msg%04d.%s\"\n", msgnum + 1, format);
- 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);
- }
- pclose(p);
- } else {
- ast_log(LOG_WARNING, "Unable to launch '%s'\n", SENDMAIL);
- return -1;
- }
- return 0;
-}
-
-static int sendpage(char *srcemail, char *pager, int msgnum, char *mailbox, char *callerid, long duration, struct ast_vm_user *vmu)
-{
- FILE *p;
- char date[256];
- char host[256];
- char who[256];
- char dur[256];
- time_t t;
- struct tm tm;
- struct vm_zone *the_zone = NULL;
- 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);
-
- /* 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);
-
- 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);
- fprintf(p, "Subject: New VM\n\n");
- strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
- fprintf(p, "New %s long msg in box %s\n"
- "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;
-}
-
-static int get_date(char *s, int len)
-{
- struct tm tm;
- time_t t;
- t = time(0);
- localtime_r(&t,&tm);
- return strftime(s, len, "%a %b %e %r %Z %Y", &tm);
-}
-
-static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
-{
- int res;
- char fn[256];
- snprintf(fn, sizeof(fn), "voicemail/%s/%s/greet", context, ext);
- if (ast_fileexists(fn, NULL, NULL) > 0) {
- res = ast_streamfile(chan, fn, chan->language);
- if (res)
- return -1;
- res = ast_waitstream(chan, ecodes);
- if (res)
- return res;
- } else {
- res = ast_streamfile(chan, "vm-theperson", chan->language);
- if (res)
- return -1;
- res = ast_waitstream(chan, ecodes);
- if (res)
- return res;
- res = ast_say_digit_str(chan, ext, ecodes, chan->language);
- if (res)
- return res;
- }
- if (busy)
- res = ast_streamfile(chan, "vm-isonphone", chan->language);
- else
- res = ast_streamfile(chan, "vm-isunavail", chan->language);
- if (res)
- return -1;
- res = ast_waitstream(chan, ecodes);
- return res;
-}
-
-static int play_and_wait(struct ast_channel *chan, char *fn)
-{
- int d;
- d = ast_streamfile(chan, fn, chan->language);
- if (d)
- return d;
- d = ast_waitstream(chan, AST_DIGIT_ANY);
- return d;
-}
-
-static int play_and_record(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];
- 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;
-
- 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);
- if (!d)
- 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];
- char txtfile[256];
- FILE *txt;
- int res = 0;
- int msgnum;
- char date[256];
- char dir[256];
- char fn[256];
- char prefile[256]="";
- char fmt[80];
- char *context;
- char *ecodes = "#";
- char *stringp;
- time_t start;
- time_t end;
- 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++;
- }
-
- if ((vmu = find_user(&svm, context, ext))) {
- /* Setup pre-file if appropriate */
- if (busy)
- snprintf(prefile, sizeof(prefile), "voicemail/%s/%s/busy", vmu->context, ext);
- else if (unavail)
- 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, "");
- /* 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, "INBOX");
- if (mkdir(dir, 0700) && (errno != EEXIST))
- ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
- if (ast_exists_extension(chan, strlen(chan->macrocontext) ? chan->macrocontext : chan->context, "o", 1, chan->callerid))
- ecodes = "#0";
- /* Play the beginning intro if desired */
- if (strlen(prefile)) {
- if (ast_fileexists(prefile, NULL, NULL) > 0) {
- if (ast_streamfile(chan, prefile, chan->language) > -1)
- res = ast_waitstream(chan, "#0");
- } else {
- ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
- res = invent_message(chan, vmu->context, ext, busy, ecodes);
- }
- if (res < 0) {
- ast_log(LOG_DEBUG, "Hang up during prefile playback\n");
- free_user(vmu);
- return -1;
- }
- }
- 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 == '#') {
- silent = 1;
- res = 0;
- }
- }
- /* Check for a '0' here */
- if (res == '0') {
- strncpy(chan->exten, "o", sizeof(chan->exten) - 1);
- if (strlen(chan->macrocontext))
- strncpy(chan->context, chan->macrocontext, sizeof(chan->context) - 1);
- chan->priority = 0;
- free_user(vmu);
- return 0;
- }
- 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,
-";\n"
-"; Message Information file\n"
-";\n"
-"[message]\n"
-"origmailbox=%s\n"
-"context=%s\n"
-"exten=%s\n"
-"priority=%d\n"
-"callerchan=%s\n"
-"callerid=%s\n"
-"origdate=%s\n"
-"origtime=%ld\n",
- ext,
- chan->context,
- chan->exten,
- chan->priority,
- chan->name,
- chan->callerid ? chan->callerid : "Unknown",
- 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");
- } else
- ast_log(LOG_WARNING, "No format for saving voicemail?\n");
- free_user(vmu);
- } else
- ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
- /* Leave voicemail for someone */
- manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext, ast_app_has_voicemail(ext));
- return res;
-}
-
-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;
- d = ast_say_number(chan, num, AST_DIGIT_ANY, chan->language);
- 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;
-}
-
-static int save_to_folder(char *dir, int msg, char *context, char *username, int box)
-{
- 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);
- make_dir(ddir, sizeof(ddir), context, username, dbox);
- 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;
-}
-
-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);
- bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
- 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, " ...", "");
- bytes += adsi_voice_mode(buf + bytes, 0);
-
- 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);
- bytes += adsi_voice_mode(buf + bytes, 0);
- 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;
- if (!adsi_available(chan))
- return;
- 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;
- unsigned char keys[8];
- int x;
- if (!adsi_available(chan))
- return;
-
- for (x=0;x<8;x++)
- 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;
- unsigned char keys[8];
- int x;
- if (!adsi_available(chan))
- return;
-
- for (x=0;x<8;x++)
- 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);
- bytes += adsi_voice_mode(buf + bytes, 0);
- 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;
- unsigned char keys[8];
- 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);
- keys[6] = 0;
- keys[7] = 0;
-
- 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);
- bytes += adsi_voice_mode(buf + bytes, 0);
-
- 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];
-
- char cid[256]="";
- char *val;
- char *name, *num;
- char datetime[21]="";
- FILE *f;
-
- unsigned char keys[8];
-
- 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)) {
- char *stringp=NULL;
- stringp=buf;
- strsep(&stringp, "=");
- val = strsep(&stringp, "=");
- 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);
- keys[6] = 0x0;
- keys[7] = 0x0;
-
- 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);
- bytes += adsi_voice_mode(buf + bytes, 0);
-
- } 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" */
-
- 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);
- bytes += adsi_voice_mode(buf + bytes, 0);
-
- 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];
- unsigned char keys[8];
-
- 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);
-
- keys[6] = 0x0;
- keys[7] = 0x0;
-
- 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);
- bytes += adsi_voice_mode(buf + bytes, 0);
-
- 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;
- unsigned char keys[8];
- 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);
- keys[6] = 0;
- keys[7] = 0;
-
- /* Don't let them listen if there are none */
- if (lastmsg < 0)
- keys[0] = 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_status2(struct ast_channel *chan, char *folder, int messages)
-{
- char buf[256], buf1[256], buf2[256];
- int bytes=0;
- unsigned char keys[8];
- 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);
-
- keys[6] = 0;
- keys[7] = 0;
-
- 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);
-
- bytes += adsi_voice_mode(buf + bytes, 0);
-
- 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);
- bytes += adsi_voice_mode(buf + bytes, 0);
-
- adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
-
-static void adsi_goodbye(struct ast_channel *chan)
-{
- char buf[256];
- int bytes=0;
-
- 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);
- bytes += adsi_voice_mode(buf + bytes, 0);
-
- adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
-}
-
-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++) {
- if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language)))
- 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;
-}
-
-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;
-}
-
-static int
-forward_message(struct ast_channel *chan, char *context, char *dir, int curmsg, struct ast_vm_user *sender, char *fmt)
-{
- char username[70];
- char sys[256];
- char todir[256];
- int todircount=0;
- long duration;
- struct ast_config *mif;
- char miffile[256];
- char fn[256];
- char callerid[512];
- int res = 0;
- struct ast_vm_user *receiver, srec;
- char tmp[256];
- char *stringp, *s;
-
- while(!res) {
- res = ast_streamfile(chan, "vm-extension", chan->language);
- if (res)
- break;
- if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
- break;
- if ((receiver = find_user(&srec, context, username))) {
- /* if (play_and_wait(chan, "vm-savedto"))
- break;
- */
-
- snprintf(todir, sizeof(todir), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, receiver->context, username);
- 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, "|"))) {
- snprintf(sys, sizeof(sys), "cp %s/msg%04d.%s %s/msg%04d.%s\n", dir, curmsg, s, todir, todircount, s);
- ast_log(LOG_DEBUG, sys);
- system(sys);
- }
- 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"));
- duration = atol(ast_variable_retrieve(mif, NULL, "duration"));
-
- if (strlen(receiver->email)) {
- int attach_user_voicemail = attach_voicemail;
- char *myserveremail = serveremail;
- if (receiver->attach > -1)
- attach_user_voicemail = receiver->attach;
- if (strlen(receiver->serveremail))
- myserveremail = receiver->serveremail;
- sendmail(myserveremail, receiver, todircount, username, callerid, fn, tmp, atol(ast_variable_retrieve(mif, NULL, "duration")), attach_user_voicemail);
- }
-
- if (strlen(receiver->pager)) {
- char *myserveremail = serveremail;
- if (strlen(receiver->serveremail))
- myserveremail = receiver->serveremail;
- sendpage(myserveremail, receiver->pager, todircount, username, callerid, duration, receiver);
- }
-
- ast_destroy(mif); /* or here */
- }
- /* Leave voicemail for someone */
- manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", username, ast_app_has_voicemail(username));
-
- /* give confirmatopm that the message was saved */
- res = play_and_wait(chan, "vm-message");
- if (!res)
- res = play_and_wait(chan, "vm-saved");
- free_user(receiver);
- break;
- } else {
- res = play_and_wait(chan, "pbx-invalid");
- }
- }
- return res;
-}
-
-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;
-};
-
-
-static int wait_file2(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(chan, AST_DIGIT_ANY);
- return res;
-}
-
-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;
- }
- z = z->next;
- }
- }
-
-/* 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);
-
- /* 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;
-}
-
-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)
- break;
- 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));
-}
-
-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;
-}
-
-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;
-}
-
-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;
-
- 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;
-}
-
-static int vm_execmain(struct ast_channel *chan, void *data)
-{
- /* 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 */
- int res=-1;
- int valid = 0;
- int prefix = 0;
- int cmd=0;
- struct localuser *u;
- char prefixstr[80] ="";
- char empty[80] = "";
- int box;
- int useadsi = 0;
- int skipuser = 0;
- char tmp[256], *ext;
- char fmtc[256] = "";
- char password[80];
- struct vm_state vms;
- int logretries = 0;
- struct ast_vm_user *vmu = NULL, vmus;
- char *context=NULL;
-
- LOCAL_USER_ADD(u);
- memset(&vms, 0, sizeof(vms));
- strncpy(fmtc, vmfmts, sizeof(fmtc) - 1);
- if (chan->_state != AST_STATE_UP)
- ast_answer(chan);
-
- if (data && strlen(data)) {
- 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;
- }
-
- context = strchr(ext, '@');
- if (context) {
- *context = '\0';
- context++;
- }
-
- if (prefix)
- strncpy(prefixstr, ext, sizeof(prefixstr) - 1);
- else
- strncpy(vms.username, ext, sizeof(vms.username) - 1);
- if (strlen(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
- skipuser++;
- else
- valid = 0;
-
- }
-
- /* If ADSI is supported, setup login screen */
- adsi_begin(chan, &useadsi);
- if (!skipuser && useadsi)
- adsi_login(chan);
- if (!skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
- ast_log(LOG_WARNING, "Couldn't stream login file\n");
- goto out;
- }
-
- /* Authenticate them and get their mailbox/password */
-
- while (!valid && (logretries < maxlogins)) {
- /* Prompt for, and read in the username */
- if (!skipuser && ast_readstring(chan, vms.username, sizeof(vms.username) - 1, 2000, 10000, "#") < 0) {
- ast_log(LOG_WARNING, "Couldn't read username\n");
- goto out;
- }
- if (!strlen(vms.username)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Username not entered\n");
- res = 0;
- goto out;
- }
- if (useadsi)
- adsi_password(chan);
- if (ast_streamfile(chan, "vm-password", chan->language)) {
- ast_log(LOG_WARNING, "Unable to stream password file\n");
- goto out;
- }
- if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
- ast_log(LOG_WARNING, "Unable to read password\n");
- goto out;
- }
- if (prefix) {
- char fullusername[80] = "";
- strncpy(fullusername, prefixstr, sizeof(fullusername) - 1);
- 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 {
- if (option_verbose > 2)
- 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);
- }
- if (!valid) {
- if (useadsi)
- adsi_login(chan);
- if (ast_streamfile(chan, "vm-incorrect", chan->language))
- break;
- }
- logretries++;
- }
- if (!valid && (logretries >= maxlogins)) {
- ast_stopstream(chan);
- res = play_and_wait(chan, "vm-goodbye");
- if (res > 0)
- res = 0;
- }
-
- if (valid) {
- 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;
- /* Start in INBOX */
- open_mailbox(&vms, vmu, 0);
- vms.newmessages = vms.lastmsg + 1;
-
-
- /* Select proper mailbox FIRST!! */
- if (!vms.newmessages && vms.oldmessages) {
- /* If we only have old messages start here */
- open_mailbox(&vms, vmu, 1);
- }
-
- if (useadsi)
- 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");
- else
- 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;
- }
- }
- if ((cmd == 't') || (cmd == '#')) {
- /* Timeout */
- res = 0;
- } else {
- /* Hangup */
- res = -1;
- }
- }
-out:
- 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);
- if (valid) {
- manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", vms.username, ast_app_has_voicemail(vms.username));
- }
- LOCAL_USER_REMOVE(u);
- return res;
-
-}
-
-static int vm_exec(struct ast_channel *chan, void *data)
-{
- int res=0, silent=0, busy=0, unavail=0;
- struct localuser *u;
- char tmp[256], *ext;
-
- LOCAL_USER_ADD(u);
- if (chan->_state != AST_STATE_UP)
- ast_answer(chan);
- if (data)
- 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;
- while(*ext) {
- if (*ext == 's') {
- silent = 2;
- ext++;
- } else if (*ext == 'b') {
- busy=1;
- ext++;
- } else if (*ext == 'u') {
- unavail=1;
- ext++;
- } else
- break;
- }
- res = leave_voicemail(chan, ext, silent, busy, unavail);
- LOCAL_USER_REMOVE(u);
- return res;
-}
-
-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());
-}
-
-int unload_module(void)
-{
- int res;
- STANDARD_HANGUP_LOCALUSERS;
- res = ast_unregister_application(app);
- res |= ast_unregister_application(app2);
- sql_close();
- return res;
-}
-
-int load_module(void)
-{
- int res;
- res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
- res |= ast_register_application(app2, 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;
- }
- return res;
-}
-
-char *description(void)
-{
- return tdesc;
-}
-
-int usecount(void)
-{
- int res;
- STANDARD_USECOUNT(res);
- return res;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}