/* IMSpector - Instant Messenger Transparent Proxy Service * http://www.imspector.org/ * (c) Lawrence Manning , 2006 * * Contributions from: * Ryan Wagoner , 2006 * * This module contributed by: * David Hinkle , 2007 * * Released under the GPL v2. */ #include "imspector.h" #include #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 &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 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 &imevents, std::string &clientaddress) { PGresult *res; /* store imevents locally in case of sql connection error */ for (std::vector::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; }