Newer
Older
Olle Johansson
committed
char full_fn[256];
char msgnums[80];
Tilghman Lesher
committed
struct odbc_obj *obj;
obj = odbc_request_obj(odbc_database, 0);
ast_copy_string(fmt, vmfmts, sizeof(fmt));
c = strchr(fmt, '|');
if (c)
*c = '\0';
if (!strcasecmp(fmt, "wav49"))
snprintf(msgnums, sizeof(msgnums),"%d", msgnum);
if (msgnum > -1)
make_file(fn, sizeof(fn), dir, msgnum);
else
snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
f = fopen(full_fn, "w+");
snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
Tilghman Lesher
committed
odbc_release_obj(obj);
snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?",odbc_table);
res = SQLPrepare(stmt, sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
res = odbc_smart_execute(obj, stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
res = SQLFetch(stmt);
if (res == SQL_NO_DATA) {
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
goto yuck;
}
fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, 0770);
Kevin P. Fleming
committed
if (fd < 0) {
ast_log(LOG_WARNING, "Failed to write '%s': %s\n", full_fn, strerror(errno));
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
goto yuck;
}
res = SQLNumResultCols(stmt, &colcount);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
goto yuck;
}
if (f)
fprintf(f, "[message]\n");
for (x=0;x<colcount;x++) {
rowdata[0] = '\0';
collen = sizeof(coltitle);
res = SQLDescribeCol(stmt, x + 1, coltitle, sizeof(coltitle), &collen,
&datatype, &colsize, &decimaldigits, &nullable);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
Kevin P. Fleming
committed
ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
if (!strcasecmp(coltitle, "recording")) {
res = SQLGetData(stmt, x + 1, SQL_BINARY, NULL, 0, &colsize);
fdlen = colsize;
if (fd > -1) {
char tmp[1]="";
lseek(fd, fdlen - 1, SEEK_SET);
if (write(fd, tmp, 1) != 1) {
close(fd);
fd = -1;
Kevin P. Fleming
committed
if (fd > -1)
fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
}
if (fdm) {
memset(fdm, 0, fdlen);
res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, fdlen, &colsize);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
}
Kevin P. Fleming
committed
} else {
res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
goto yuck;
}
if (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir") && f)
fprintf(f, "%s=%s\n", coltitle, rowdata);
Kevin P. Fleming
committed
}
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
if (f)
fclose(f);
if (fdm)
munmap(fdm, fdlen);
if (fd > -1)
close(fd);
return x - 1;
}
static int remove_file(char *dir, int msgnum)
{
Olle Johansson
committed
char fn[256];
char full_fn[256];
char msgnums[80];
if (msgnum > -1) {
snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
make_file(fn, sizeof(fn), dir, msgnum);
} else
ast_filedelete(fn, NULL);
snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
unlink(full_fn);
return 0;
}
static int last_message_index(struct ast_vm_user *vmu, char *dir)
{
int x = 0;
int res;
SQLHSTMT stmt;
char sql[256];
char rowdata[20];
Tilghman Lesher
committed
struct odbc_obj *obj;
obj = odbc_request_obj(odbc_database, 0);
if (obj) {
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
Tilghman Lesher
committed
odbc_release_obj(obj);
snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?",odbc_table);
res = SQLPrepare(stmt, sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
res = odbc_smart_execute(obj, stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
res = SQLFetch(stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
if (sscanf(rowdata, "%d", &x) != 1)
ast_log(LOG_WARNING, "Failed to read message count!\n");
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
return x - 1;
}
static int message_exists(char *dir, int msgnum)
{
int x = 0;
int res;
SQLHSTMT stmt;
char sql[256];
char rowdata[20];
Olle Johansson
committed
char msgnums[20];
Tilghman Lesher
committed
struct odbc_obj *obj;
obj = odbc_request_obj(odbc_database, 0);
if (obj) {
snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
Tilghman Lesher
committed
odbc_release_obj(obj);
snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?",odbc_table);
res = SQLPrepare(stmt, sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
res = odbc_smart_execute(obj, stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
res = SQLFetch(stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
Kevin P. Fleming
committed
if (sscanf(rowdata, "%d", &x) != 1)
ast_log(LOG_WARNING, "Failed to read message count!\n");
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
return x;
}
static int count_messages(struct ast_vm_user *vmu, char *dir)
return last_message_index(vmu, dir) + 1;
static void delete_file(char *sdir, int smsg)
{
int res;
SQLHSTMT stmt;
char sql[256];
Olle Johansson
committed
char msgnums[20];
Tilghman Lesher
committed
struct odbc_obj *obj;
obj = odbc_request_obj(odbc_database, 0);
if (obj) {
snprintf(msgnums, sizeof(msgnums), "%d", smsg);
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
Tilghman Lesher
committed
odbc_release_obj(obj);
snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE dir=? AND msgnum=?",odbc_table);
res = SQLPrepare(stmt, sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL);
SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
res = odbc_smart_execute(obj, stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
return;
}
static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext)
{
int res;
SQLHSTMT stmt;
Olle Johansson
committed
char msgnums[20];
char msgnumd[20];
Tilghman Lesher
committed
struct odbc_obj *obj;
delete_file(ddir, dmsg);
Tilghman Lesher
committed
obj = odbc_request_obj(odbc_database, 0);
if (obj) {
snprintf(msgnums, sizeof(msgnums), "%d", smsg);
snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
Tilghman Lesher
committed
odbc_release_obj(obj);
snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, context, macrocontext, callerid, origtime, duration, recording, mailboxuser, mailboxcontext) SELECT ?,?,context,macrocontext,callerid,origtime,duration,recording,?,? FROM %s WHERE dir=? AND msgnum=?",odbc_table,odbc_table);
res = SQLPrepare(stmt, sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ddir), 0, (void *)ddir, 0, NULL);
SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnumd), 0, (void *)msgnumd, 0, NULL);
SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dmailboxuser), 0, (void *)dmailboxuser, 0, NULL);
SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dmailboxcontext), 0, (void *)dmailboxcontext, 0, NULL);
SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL);
SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
res = odbc_smart_execute(obj, stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
return;
}
static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum)
{
int x = 0;
int res;
int fd = -1;
void *fdm=NULL;
size_t fdlen = -1;
SQLHSTMT stmt;
SQLINTEGER len;
char sql[256];
Olle Johansson
committed
char msgnums[20];
char fn[256];
char full_fn[256];
char fmt[80]="";
char *c;
char *context="", *macrocontext="", *callerid="", *origtime="", *duration="";
struct ast_config *cfg=NULL;
Tilghman Lesher
committed
struct odbc_obj *obj;
delete_file(dir, msgnum);
Tilghman Lesher
committed
obj = odbc_request_obj(odbc_database, 0);
ast_copy_string(fmt, vmfmts, sizeof(fmt));
c = strchr(fmt, '|');
if (c)
*c = '\0';
if (!strcasecmp(fmt, "wav49"))
snprintf(msgnums, sizeof(msgnums),"%d", msgnum);
if (msgnum > -1)
make_file(fn, sizeof(fn), dir, msgnum);
else
snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
fd = open(full_fn, O_RDWR);
if (fd < 0) {
ast_log(LOG_WARNING, "Open of sound file '%s' failed: %s\n", full_fn, strerror(errno));
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
if (cfg) {
context = ast_variable_retrieve(cfg, "message", "context");
if (!context) context = "";
macrocontext = ast_variable_retrieve(cfg, "message", "macrocontext");
if (!macrocontext) macrocontext = "";
callerid = ast_variable_retrieve(cfg, "message", "callerid");
if (!callerid) callerid = "";
origtime = ast_variable_retrieve(cfg, "message", "origtime");
if (!origtime) origtime = "";
duration = ast_variable_retrieve(cfg, "message", "duration");
if (!duration) duration = "";
category = ast_variable_retrieve(cfg, "message", "category");
if (!category) category = "";
}
fdlen = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
Russell Bryant
committed
printf("Length is %zd\n", fdlen);
fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
if (!fdm) {
ast_log(LOG_WARNING, "Memory map failed!\n");
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
Tilghman Lesher
committed
odbc_release_obj(obj);
snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,category) VALUES (?,?,?,?,?,?,?,?,?,?,?)",odbc_table);
snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext) VALUES (?,?,?,?,?,?,?,?,?,?)",odbc_table);
res = SQLPrepare(stmt, sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
len = fdlen; /* SQL_LEN_DATA_AT_EXEC(fdlen); */
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, fdlen, 0, (void *)fdm, fdlen, &len);
SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(context), 0, (void *)context, 0, NULL);
SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(macrocontext), 0, (void *)macrocontext, 0, NULL);
SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(callerid), 0, (void *)callerid, 0, NULL);
SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(origtime), 0, (void *)origtime, 0, NULL);
SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(duration), 0, (void *)duration, 0, NULL);
SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxuser), 0, (void *)mailboxuser, 0, NULL);
SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxcontext), 0, (void *)mailboxcontext, 0, NULL);
if (!ast_strlen_zero(category))
SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(category), 0, (void *)category, 0, NULL);
res = odbc_smart_execute(obj, stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
if (cfg)
if (fdm)
munmap(fdm, fdlen);
if (fd > -1)
close(fd);
return x;
}
static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxcontext, char *ddir, int dmsg)
{
int res;
SQLHSTMT stmt;
char sql[256];
Olle Johansson
committed
char msgnums[20];
char msgnumd[20];
Tilghman Lesher
committed
struct odbc_obj *obj;
delete_file(ddir, dmsg);
Tilghman Lesher
committed
obj = odbc_request_obj(odbc_database, 0);
if (obj) {
snprintf(msgnums, sizeof(msgnums), "%d", smsg);
snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
Tilghman Lesher
committed
odbc_release_obj(obj);
snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?",odbc_table);
res = SQLPrepare(stmt, sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ddir), 0, (void *)ddir, 0, NULL);
SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnumd), 0, (void *)msgnumd, 0, NULL);
SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxuser), 0, (void *)mailboxuser, 0, NULL);
SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxcontext), 0, (void *)mailboxcontext, 0, NULL);
SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL);
SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
res = odbc_smart_execute(obj, stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
goto yuck;
}
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
Tilghman Lesher
committed
odbc_release_obj(obj);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
return;
}
#else
static int count_messages(struct ast_vm_user *vmu, char *dir)
/* Find all .txt files - even if they are not in sequence from 0000 */
int vmcount = 0;
DIR *vmdir = NULL;
struct dirent *vment = NULL;
return ERROR_LOCK_PATH;
if ((vmdir = opendir(dir))) {
while ((vment = readdir(vmdir))) {
if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4))
vmcount++;
}
closedir(vmdir);
ast_unlock_path(dir);
return vmcount;
}
static void rename_file(char *sfn, char *dfn)
{
Olle Johansson
committed
char stxt[256];
char dtxt[256];
ast_filerename(sfn,dfn,NULL);
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
rename(stxt, dtxt);
}
static int copy(char *infile, char *outfile)
{
int ifd;
int ofd;
int res;
int len;
char buf[4096];
#ifdef HARDLINK_WHEN_POSSIBLE
/* Hard link if possible; saves disk space & is faster */
if (link(infile, outfile)) {
#endif
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, VOICEMAIL_FILE_MODE)) < 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 (errno == ENOMEM || errno == ENOSPC || 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;
#ifdef HARDLINK_WHEN_POSSIBLE
} else {
/* Hard link succeeded */
return 0;
}
#endif
}
static void copy_file(char *frompath, char *topath)
{
Olle Johansson
committed
char frompath2[256],topath2[256];
ast_filecopy(frompath, topath, NULL);
snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
snprintf(topath2, sizeof(topath2), "%s.txt", topath);
copy(frompath2, topath2);
}
/*
* A negative return value indicates an error.
* \note Should always be called with a lock already set on dir.
static int last_message_index(struct ast_vm_user *vmu, char *dir)
Joshua Colp
committed
unsigned char map[MAXMSGLIMIT] = "";
DIR *msgdir;
struct dirent *msgdirent;
int msgdirint;
Joshua Colp
committed
/* Reading the entire directory into a file map scales better than
* doing a stat repeatedly on a predicted sequence. I suspect this
* is partially due to stat(2) internally doing a readdir(2) itself to
* find each file. */
msgdir = opendir(dir);
while ((msgdirent = readdir(msgdir))) {
if (sscanf(msgdirent->d_name, "msg%d", &msgdirint) == 1 && msgdirint < MAXMSGLIMIT)
map[msgdirint] = 1;
}
closedir(msgdir);
for (x = 0; x < vmu->maxmsg; x++) {
Joshua Colp
committed
if (map[x] == 0)
static int vm_delete(char *file)
{
char *txt;
int txtsize = 0;
txtsize = (strlen(file) + 5)*sizeof(char);
BJ Weschke
committed
txt = alloca(txtsize);
/* Sprintf here would safe because we alloca'd exactly the right length,
* but trying to eliminate all sprintf's anyhow
*/
snprintf(txt, txtsize, "%s.txt", file);
unlink(txt);
return ast_filedelete(file, NULL);
}
#endif
static int inbuf(struct baseio *bio, FILE *fi)
if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
if (ferror(fi))
bio->ateof = 1;
bio->iolen= l;
bio->iocp= 0;
static int inchar(struct baseio *bio, FILE *fi)
if (bio->iocp>=bio->iolen) {
if (!inbuf(bio, fi))
return bio->iobuf[bio->iocp++];
static int ochar(struct baseio *bio, int c, FILE *so)
if (bio->linelength>=BASELINELEN) {
if (fputs(eol,so)==EOF)
bio->linelength= 0;
if (putc(((unsigned char)c),so)==EOF)
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;
}
dtable[i]= 'A'+i;
dtable[i+9]= 'J'+i;
dtable[26+i]= 'a'+i;
dtable[26+i+9]= 'j'+i;
}
dtable[i+18]= 'S'+i;
dtable[26+i+18]= 's'+i;
}
dtable[52+i]= '0'+i;
}
dtable[62]= '+';
dtable[63]= '/';
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;
}
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];
ochar(&bio, ogroup[i], so);
return 0;
fclose(fi);
return 1;
}
static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *dur, char *date, char *passdata, size_t passdatasize, const char *category)
/* Prepare variables for substition in email body and subject */
pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
snprintf(passdata, passdatasize, "%d", msgnum);
pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
pbx_builtin_setvar_helper(ast, "VM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (cidname ? cidname : "an unknown caller"));
pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
pbx_builtin_setvar_helper(ast, "VM_DATE", date);
pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
/*
* fill in *tm for current time according to the proper timezone, if any.
* Return tm so it can be used as a function argument.
*/
static const struct tm *vmu_tm(const struct ast_vm_user *vmu, struct tm *tm)
{
const struct vm_zone *z = NULL;
time_t t = time(NULL);
/* Does this user have a timezone specified? */
if (!ast_strlen_zero(vmu->zonetag)) {
/* Find the zone in the list */
Russell Bryant
committed
AST_LIST_LOCK(&zones);
AST_LIST_TRAVERSE(&zones, z, list) {
if (!strcmp(z->name, vmu->zonetag))
break;
Russell Bryant
committed
}
AST_LIST_UNLOCK(&zones);
}
ast_localtime(&t, tm, z ? z->timezone : NULL);
return tm;
}
/* same as mkstemp, but return a FILE * */
static FILE *vm_mkftemp(char *template)
{
FILE *p = NULL;
int pfd = mkstemp(template);
if (pfd > -1) {
p = fdopen(pfd, "w");
if (!p) {
close(pfd);
pfd = -1;
}
}
return p;
}
static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category)
Mark Spencer
committed
FILE *p=NULL;
char host[MAXHOSTNAMELEN] = "";
Olle Johansson
committed
char fname[256];
Olle Johansson
committed
char tmp[80] = "/tmp/astmail-XXXXXX";
char tmp2[256];
Tilghman Lesher
committed
char tmpcmd[256];
James Golovich
committed
if (vmu && ast_strlen_zero(vmu->email)) {
ast_log(LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
if (!strcmp(format, "wav49"))
format = "WAV";
if (option_debug)
ast_log(LOG_DEBUG, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
Mark Spencer
committed
/* Make a temporary file instead of piping directly to sendmail, in case the mail
command hangs */
if ((p = vm_mkftemp(tmp)) == NULL) {
ast_log(LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
gethostname(host, sizeof(host)-1);
ast_copy_string(who, srcemail, sizeof(who));
else {
snprintf(who, sizeof(who), "%s@%s", srcemail, host);
}
Mark Spencer
committed
snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
Kevin P. Fleming
committed
/* Set date format for voicemail mail */
strftime(date, sizeof(date), emaildateformat, &tm);
if (*fromstring) {
BJ Weschke
committed
struct ast_channel *ast;
if ((ast = ast_channel_alloc(0))) {
char *passdata;
int vmlen = strlen(fromstring)*3 + 200;
if ((passdata = alloca(vmlen))) {
memset(passdata, 0, vmlen);
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
Olle Johansson
committed
pbx_substitute_variables_helper(ast, fromstring, passdata, vmlen);
fprintf(p, "From: %s <%s>\n",passdata,who);
Olle Johansson
committed
} else
ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
ast_channel_free(ast);
Olle Johansson
committed
} else
ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
fprintf(p, "From: Asterisk PBX <%s>\n", who);
fprintf(p, "To: %s <%s>\n", vmu->fullname, vmu->email);
if (emailsubject) {
BJ Weschke
committed
struct ast_channel *ast;
if ((ast = ast_channel_alloc(0))) {
char *passdata;
int vmlen = strlen(emailsubject)*3 + 200;
if ((passdata = alloca(vmlen))) {
memset(passdata, 0, vmlen);
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
Olle Johansson
committed
pbx_substitute_variables_helper(ast, emailsubject, passdata, vmlen);
fprintf(p, "Subject: %s\n", passdata);
} else
ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
ast_channel_free(ast);
Olle Johansson
committed
} else
ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
fprintf(p, emailtitle, msgnum + 1, mailbox) ;
fprintf(p,"\n") ;
} else if (ast_test_flag((&globalflags), VM_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);
Tilghman Lesher
committed
fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>\n", msgnum, (unsigned int)ast_random(), mailbox, getpid(), host);
#ifdef IMAP_STORAGE
/* additional information needed for IMAP searching */
fprintf(p, "X-Asterisk-VM-Message-Num: %d\n", msgnum + 1);
/* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s\n", ext); */
fprintf(p, "X-Asterisk-VM-Server-Name: %s\n", fromstring);
fprintf(p, "X-Asterisk-VM-Context: %s\n", context);
fprintf(p, "X-Asterisk-VM-Extension: %s\n", chan->exten);
fprintf(p, "X-Asterisk-VM-Priority: %d\n", chan->priority);
fprintf(p, "X-Asterisk-VM-Caller-channel: %s\n", chan->name);
fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s\n", cidnum);
fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s\n", cidname);
fprintf(p, "X-Asterisk-VM-Duration: %d\n", duration);
if (!ast_strlen_zero(category))
fprintf(p, "X-Asterisk-VM-Category: %s\n", category);
fprintf(p, "X-Asterisk-VM-Orig-date: %s\n", date);
fprintf(p, "X-Asterisk-VM-Orig-time: %ld\n", (long)time(NULL));
#endif
Olle Johansson
committed
if (!ast_strlen_zero(cidnum))
fprintf(p, "X-Asterisk-CallerID: %s\n", cidnum);
if (!ast_strlen_zero(cidname))
fprintf(p, "X-Asterisk-CallerIDName: %s\n", cidname);
if (attach_user_voicemail) {
Tilghman Lesher
committed
snprintf(bound, sizeof(bound), "voicemail_%d%s%d%d", msgnum, mailbox, getpid(), (unsigned int)ast_random());
fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", charset);
if (emailbody) {
BJ Weschke
committed
struct ast_channel *ast;
if ((ast = ast_channel_alloc(0))) {
char *passdata;
int vmlen = strlen(emailbody)*3 + 200;
if ((passdata = alloca(vmlen))) {
memset(passdata, 0, vmlen);
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
Olle Johansson
committed
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);
Olle Johansson
committed
} 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, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
}
if (attach_user_voicemail) {
/* Eww. We want formats to tell us their own MIME type */
Olle Johansson
committed
char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
Tilghman Lesher
committed
char tmpdir[256], newtmp[256];
int tmpfd;
Tilghman Lesher
committed
create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
tmpfd = mkstemp(newtmp);
if (option_debug)
ast_log(LOG_DEBUG, "newtmp: %s\n", newtmp);
Tilghman Lesher
committed
if (vmu->volgain < -.001 || vmu->volgain > .001) {
snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
ast_safe_system(tmpcmd);
attach = newtmp;
if (option_debug)
ast_log(LOG_DEBUG, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
Tilghman Lesher
committed
}