All pastes #628167 Raw Edit

Miscellany

public text v1 · immutable
·published 2007-07-20 19:53 UTC
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;
}