Skip to content
Snippets Groups Projects
Commit 9c7099fa authored by Sean Bright's avatar Sean Bright
Browse files

Log the userfield CDR variable like the other CDR backends, assuming the

column is actually there.  If it's not, we still log everything else as
before.

(closes issue #13281)
Reported by: falves11


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@137203 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent 37133a69
Branches
Tags
No related merge requests found
...@@ -168,7 +168,8 @@ CDR: ...@@ -168,7 +168,8 @@ CDR:
systemname was too long, the uniqueid would have been truncated. systemname was too long, the uniqueid would have been truncated.
* The cdr_tds module now supports all versions of FreeTDS that contain * The cdr_tds module now supports all versions of FreeTDS that contain
the db-lib frontend. the db-lib frontend. It will also now log the userfield variable if
the target database table contains a column for it.
Formats: Formats:
......
...@@ -48,7 +48,8 @@ CREATE TABLE [dbo].[cdr] ( ...@@ -48,7 +48,8 @@ CREATE TABLE [dbo].[cdr] (
[billsec] [int] NULL , [billsec] [int] NULL ,
[disposition] [varchar] (20) NULL , [disposition] [varchar] (20) NULL ,
[amaflags] [varchar] (16) NULL , [amaflags] [varchar] (16) NULL ,
[uniqueid] [varchar] (32) NULL [uniqueid] [varchar] (32) NULL ,
[userfield] [varchar] (256) NULL
) ON [PRIMARY] ) ON [PRIMARY]
\endverbatim \endverbatim
...@@ -91,6 +92,7 @@ struct cdr_tds_config { ...@@ -91,6 +92,7 @@ struct cdr_tds_config {
); );
DBPROCESS *dbproc; DBPROCESS *dbproc;
unsigned int connected:1; unsigned int connected:1;
unsigned int has_userfield:1;
}; };
AST_MUTEX_DEFINE_STATIC(tds_lock); AST_MUTEX_DEFINE_STATIC(tds_lock);
...@@ -100,13 +102,16 @@ static struct cdr_tds_config *settings; ...@@ -100,13 +102,16 @@ static struct cdr_tds_config *settings;
static char *anti_injection(const char *, int); static char *anti_injection(const char *, int);
static void get_date(char *, size_t len, struct timeval); static void get_date(char *, size_t len, struct timeval);
static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
static int mssql_connect(void); static int mssql_connect(void);
static int mssql_disconnect(void); static int mssql_disconnect(void);
static int tds_log(struct ast_cdr *cdr) static int tds_log(struct ast_cdr *cdr)
{ {
char start[80], answer[80], end[80]; char start[80], answer[80], end[80];
char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid; char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid, *userfield = NULL;
RETCODE erc; RETCODE erc;
int res = -1; int res = -1;
...@@ -127,6 +132,10 @@ static int tds_log(struct ast_cdr *cdr) ...@@ -127,6 +132,10 @@ static int tds_log(struct ast_cdr *cdr)
ast_mutex_lock(&tds_lock); ast_mutex_lock(&tds_lock);
if (settings->has_userfield) {
userfield = anti_injection(cdr->userfield, AST_MAX_USER_FIELD);
}
/* Ensure that we are connected */ /* Ensure that we are connected */
if (!settings->connected) { if (!settings->connected) {
if (mssql_connect()) { if (mssql_connect()) {
...@@ -135,66 +144,46 @@ static int tds_log(struct ast_cdr *cdr) ...@@ -135,66 +144,46 @@ static int tds_log(struct ast_cdr *cdr)
} }
} }
erc = dbfcmd(settings->dbproc, if (settings->has_userfield) {
"INSERT INTO %s " erc = dbfcmd(settings->dbproc,
"(" "INSERT INTO %s "
"accountcode, " "("
"src, " "accountcode, src, dst, dcontext, clid, channel, "
"dst, " "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
"dcontext, " "billsec, disposition, amaflags, uniqueid, userfield"
"clid, " ") "
"channel, " "VALUES "
"dstchannel, " "("
"lastapp, " "'%s', '%s', '%s', '%s', '%s', '%s', "
"lastdata, " "'%s', '%s', '%s', %s, %s, %s, %ld, "
"start, " "%ld, '%s', '%s', '%s', '%s'"
"answer, " ")",
"[end], " settings->table,
"duration, " accountcode, src, dst, dcontext, clid, channel,
"billsec, " dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
"disposition, " cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid,
"amaflags, " userfield
"uniqueid" );
") " } else {
"VALUES " erc = dbfcmd(settings->dbproc,
"(" "INSERT INTO %s "
"'%s', " /* accountcode */ "("
"'%s', " /* src */ "accountcode, src, dst, dcontext, clid, channel, "
"'%s', " /* dst */ "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
"'%s', " /* dcontext */ "billsec, disposition, amaflags, uniqueid"
"'%s', " /* clid */ ") "
"'%s', " /* channel */ "VALUES "
"'%s', " /* dstchannel */ "("
"'%s', " /* lastapp */ "'%s', '%s', '%s', '%s', '%s', '%s', "
"'%s', " /* lastdata */ "'%s', '%s', '%s', %s, %s, %s, %ld, "
"%s, " /* start */ "%ld, '%s', '%s', '%s'"
"%s, " /* answer */ ")",
"%s, " /* end */ settings->table,
"%ld, " /* duration */ accountcode, src, dst, dcontext, clid, channel,
"%ld, " /* billsec */ dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
"'%s', " /* disposition */ cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid
"'%s', " /* amaflags */ );
"'%s'" /* uniqueid */ }
")",
settings->table,
accountcode,
src,
dst,
dcontext,
clid,
channel,
dstchannel,
lastapp,
lastdata,
start,
answer,
end,
cdr->duration,
cdr->billsec,
ast_cdr_disp2str(cdr->disposition),
ast_cdr_flags2str(cdr->amaflags),
uniqueid
);
if (erc == FAIL) { if (erc == FAIL) {
ast_log(LOG_ERROR, "Failed to build INSERT statement, no CDR was logged.\n"); ast_log(LOG_ERROR, "Failed to build INSERT statement, no CDR was logged.\n");
...@@ -228,6 +217,10 @@ done: ...@@ -228,6 +217,10 @@ done:
ast_free(lastdata); ast_free(lastdata);
ast_free(uniqueid); ast_free(uniqueid);
if (userfield) {
ast_free(userfield);
}
return res; return res;
} }
...@@ -277,6 +270,37 @@ static void get_date(char *dateField, size_t len, struct timeval when) ...@@ -277,6 +270,37 @@ static void get_date(char *dateField, size_t len, struct timeval when)
} }
} }
static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...)
{
va_list ap;
char *buffer;
va_start(ap, fmt);
if (vasprintf(&buffer, fmt, ap) < 0) {
va_end(ap);
return 1;
}
va_end(ap);
if (dbfcmd(dbproc, buffer) == FAIL) {
free(buffer);
return 1;
}
free(buffer);
if (dbsqlexec(dbproc) == FAIL) {
return 1;
}
/* Consume the result set (we don't really care about the result, though) */
while (dbresults(dbproc) != NO_MORE_RESULTS) {
while (dbnextrow(dbproc) != NO_MORE_ROWS);
}
return 0;
}
static int mssql_disconnect(void) static int mssql_disconnect(void)
{ {
if (settings->dbproc) { if (settings->dbproc) {
...@@ -317,19 +341,17 @@ static int mssql_connect(void) ...@@ -317,19 +341,17 @@ static int mssql_connect(void)
goto failed; goto failed;
} }
if (dbfcmd(settings->dbproc, "SELECT 1 FROM [%s]", settings->table) == FAIL) { if (execute_and_consume(settings->dbproc, "SELECT 1 FROM [%s]", settings->table)) {
ast_log(LOG_ERROR, "Unable to build query while verifying the existence of table '%s'\n", settings->table); ast_log(LOG_ERROR, "Unable to find table '%s'\n", settings->table);
goto failed; goto failed;
} }
if (dbsqlexec(settings->dbproc) == FAIL) { /* Check to see if we have a userfield column in the table */
ast_log(LOG_ERROR, "Unable to verify existence of table '%s'\n", settings->table); if (execute_and_consume(settings->dbproc, "SELECT userfield FROM [%s] WHERE 1 = 0", settings->table)) {
goto failed; ast_log(LOG_NOTICE, "Unable to find 'userfield' column in table '%s'\n", settings->table);
} settings->has_userfield = 0;
} else {
/* Consume the result set (we don't really care about the result, though) */ settings->has_userfield = 1;
while (dbresults(settings->dbproc) != NO_MORE_RESULTS) {
while (dbnextrow(settings->dbproc) != NO_MORE_ROWS);
} }
settings->connected = 1; settings->connected = 1;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment