rendered paste body/* IMSpector - Instant Messenger Transparent Proxy Service
* http://www.imspector.org/
* (c) Lawrence Manning <lawrence@aslak.net>, 2006
*
* Contributions from:
* Ryan Wagoner <ryan@wgnrs.dynu.com>, 2006
*
* This module contributed by:
* David Hinkle <hinkle@cipafilter.com>, 2007
*
* Released under the GPL v2. */
#include "imspector.h"
#include <libpq-fe.h>
#define FALSE 0
#define TRUE 1
#define PLUGIN_NAME "PostgreSQL IMSpector logging plugin"
#define PLUGIN_SHORT_NAME "PGSQL"
#define CREATE_TABLE "CREATE TABLE imspector_messages ( " \
"id serial primary key, " \
"\"timestamp\" timestamp with time zone default now(), " \
"protocolname varchar, " \
"type int default 0, " \
"localid varchar, " \
"remoteid varchar, " \
"eventdata text )"
#define INSERT_STATEMENT "INSERT INTO imspector_messages " \
"(timestamp, protocolname, type, localid, remoteid, eventdata) " \
"VALUES (timestamptz 'epoch' + $1 * INTERVAL '1 second', $2, $3, $4, $5, $6)"
#define NO_FIELDS 6
extern "C"
{
bool initloggingplugin(struct loggingplugininfo &ploggingplugininfo,
class Options &options, bool debugmode);
int logevents(std::vector<struct imevent> &imevents, std::string &clientaddress);
};
PGconn *conn = NULL;
char timestamp[STRING_SIZE];
char protocolname[STRING_SIZE];
char type[STRING_SIZE];
char localid[STRING_SIZE];
char remoteid[STRING_SIZE];
char eventdata[BUFFER_SIZE];
const char *paramValues[NO_FIELDS] = { timestamp, protocolname, type, localid, remoteid, eventdata };
bool localdebugmode = false;
bool connected = false;
int retries = 0;
std::string connect_string;
std::vector<struct imevent> pgsqlevents;
bool connectpgsql(void);
bool initloggingplugin(struct loggingplugininfo &loggingplugininfo,
class Options &options, bool debugmode)
{
localdebugmode = debugmode;
loggingplugininfo.pluginname = PLUGIN_NAME;
if (options["pgsql_connect"] == "") return false;
connect_string = options["pgsql_connect"];
return connected = connectpgsql();
}
void closeloggingplugin(void)
{
PQfinish(conn);
conn = NULL;
return;
}
/* The main plugin function. See loggingplugin.cpp. */
int logevents(std::vector<struct imevent> &imevents, std::string &clientaddress)
{
PGresult *res;
/* store imevents locally in case of sql connection error */
for (std::vector<struct imevent>::iterator i = imevents.begin(); i != imevents.end(); i++)
pgsqlevents.push_back(*i);
/* try and process local imevents */
while (pgsqlevents.size())
{
struct imevent imevent = pgsqlevents.front();
snprintf(timestamp, STRING_SIZE, "%ld", imevent.timestamp);
strncpy(protocolname, imevent.protocolname.c_str(), STRING_SIZE - 1);
snprintf(type, STRING_SIZE, "%d", imevent.type);
strncpy(localid, imevent.localid.c_str(), STRING_SIZE - 1);
strncpy(remoteid, imevent.remoteid.c_str(), STRING_SIZE - 1);
strncpy(eventdata, imevent.eventdata.c_str(), BUFFER_SIZE - 1);
/* if not connected try and connect */
if (!connected)
{
retries++;
if ((retries <= 2) || ((retries % 10) == 0))
{
if ( (connected = connectpgsql()) )
{
syslog(LOG_NOTICE, PLUGIN_SHORT_NAME ": Reconnected to database, "\
"pending events will now be logged");
retries = 0;
}
/* still not able to connect, user will get the connection attempt errors,
* lets not fill log with uneeded error messages */
else
return 0;
}
}
/* we're connected insert the data */
if (connected)
{
res = PQexecParams(conn, INSERT_STATEMENT,
NO_FIELDS, /* seven param */
NULL, /* let the backend deduce param type */
paramValues,
NULL, /* don't need param lengths since text */
NULL, /* default to all text params */
0); /* ask for binary results */
if ( PQresultStatus(res) != PGRES_COMMAND_OK )
{
syslog(LOG_ERR, PLUGIN_SHORT_NAME ": PQexecParams(), Error: %s", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
conn = NULL;
connected = FALSE;
return(TRUE);
}
else
{
PQclear(res);
pgsqlevents.erase(pgsqlevents.begin());
}
}
}
return 0;
}
bool connectpgsql(void)
{
PGresult *res;
/* Eu mudei essa linha de baixo aqui tem ve se rola */
conn = PQsetdbLogin("localhost","5432",NULL,NULL,"uniconet_rc2","postgres","un1c0ctrl2007db");
/* Check to see that the backend connection was successfully made */
if (PQstatus(conn) != CONNECTION_OK)
{
syslog(LOG_ERR, PLUGIN_SHORT_NAME ": Connection to database '%s' failed: %s", connect_string.c_str(), PQerrorMessage(conn));
PQfinish(conn);
conn = NULL;
return false;
}
res = PQexec(conn, "select tablename from pg_tables where tablename='imspector_messages';");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
syslog(LOG_ERR, PLUGIN_SHORT_NAME ": Postresql Select failed: %s", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
conn = NULL;
return false;
}
if (PQntuples(res) == 1)
{
PQclear(res);
return true;
}
PQclear(res);
syslog(LOG_ERR, PLUGIN_SHORT_NAME ": Creating new Postgresql schema");
res = PQexec(conn, CREATE_TABLE);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
syslog(LOG_ERR, PLUGIN_SHORT_NAME ": Postresql create log table transaction failed: %s", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
conn = NULL;
return false;
}
PQclear(res);
return true;
}