"Fossies" - the Fresh Open Source Software Archive

Member "mod_log_sql-1.101/mod_log_sql_pgsql.c" (9 Feb 2005, 7085 Bytes) of package /linux/www/apache_httpd_modules/old/mod_log_sql-1.101.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "mod_log_sql_pgsql.c": 1.100_vs_1.101.

    1 /* $Id: mod_log_sql_pgsql.c 165 2005-02-09 01:25:40Z urkle@drip.ws $ */
    2 
    3 #if defined(WITH_APACHE20)
    4 #   include "apache20.h"
    5 #elif defined(WITH_APACHE13)
    6 #   include "apache13.h"
    7 #else
    8 #   error Unsupported Apache version
    9 #endif
   10 
   11 
   12 #ifdef HAVE_CONFIG_H
   13 /* Undefine these to prevent conflicts between Apache ap_config_auto.h and 
   14  * my config.h. Only really needed for Apache < 2.0.48, but it can't hurt.
   15  */
   16 #undef PACKAGE_BUGREPORT
   17 #undef PACKAGE_NAME
   18 #undef PACKAGE_STRING
   19 #undef PACKAGE_TARNAME
   20 #undef PACKAGE_VERSION
   21 
   22 #include "config.h"
   23 #endif
   24 
   25 #include "mod_log_sql.h"
   26 
   27 #include "libpq-fe.h"
   28 
   29 /* Connect to the PGSQL database */
   30 static logsql_opendb_ret log_sql_pgsql_connect(server_rec *s, logsql_dbconnection *db)
   31 {
   32     const char *host = apr_table_get(db->parms,"hostname");
   33     const char *user = apr_table_get(db->parms,"username");
   34     const char *passwd = apr_table_get(db->parms,"password");
   35     const char *database = apr_table_get(db->parms,"database");
   36     const char *s_tcpport = apr_table_get(db->parms,"port");
   37     
   38     db->handle = PQsetdbLogin(host, s_tcpport, NULL, NULL, database, user, passwd);
   39 
   40     if (PQstatus(db->handle) == CONNECTION_OK) {
   41         log_error(APLOG_MARK,APLOG_DEBUG,0, s,"HOST: '%s' PORT: '%s' DB: '%s' USER: '%s'",
   42                 host, s_tcpport, database, user);
   43         return LOGSQL_OPENDB_SUCCESS;
   44     } else {
   45         log_error(APLOG_MARK,APLOG_DEBUG,0, s,"mod_log_sql: database connection error: %s",
   46                 PQerrorMessage(db->handle));
   47         log_error(APLOG_MARK,APLOG_DEBUG, 0, s,"HOST: '%s' PORT: '%s' DB: '%s' USER: '%s'",
   48                 host, s_tcpport, database, user);
   49         return LOGSQL_OPENDB_FAIL;
   50     }
   51 }
   52 
   53 /* Close the DB link */
   54 static void log_sql_pgsql_close(logsql_dbconnection *db)
   55 {
   56     PQfinish((PGconn*)(db->handle));
   57 }
   58 
   59 /* Routine to escape the 'dangerous' characters that would otherwise
   60  * corrupt the INSERT string: ', \, and "
   61  * Also PQescapeString does not place the ' around the string. So we have
   62  * to do this manually
   63  */
   64 static const char *log_sql_pgsql_escape(const char *from_str, apr_pool_t *p, 
   65                                 logsql_dbconnection *db)
   66 {
   67     char *temp;
   68     if (!from_str)
   69         return NULL;
   70     else {
   71         char *to_str;
   72         unsigned long length = strlen(from_str);
   73         unsigned long retval;
   74 
   75         /* Pre-allocate a new string that could hold twice the original, which would only
   76          * happen if the whole original string was 'dangerous' characters. 
   77          * And forsee the space for the 2 '
   78          */
   79         temp = to_str = (char *) apr_palloc(p, length * 2 + 3);
   80         if (!to_str) {
   81             return from_str;
   82         }
   83 
   84         *temp = '\'';
   85         temp++;
   86         
   87         retval = PQescapeString(temp, from_str, length);
   88         
   89         /* avoid the string to be tolong for the sql database*/
   90         if (retval > 250) retval = 250;
   91         
   92         *(temp+retval) = '\'';
   93         *(temp+retval+1) = '\0';
   94         
   95         /* We must always return the to_str, because we always need the ' added */
   96 //      if (retval)
   97           return to_str;
   98 //      else
   99 //        return from_str;
  100     }
  101 }
  102 
  103 /* Run a sql insert query and return a categorized error or success */
  104 static logsql_query_ret log_sql_pgsql_query(request_rec *r,logsql_dbconnection *db,
  105                                 const char *query)
  106 {
  107     PGresult *result;
  108     void (*handler) (int);
  109     unsigned int real_error = 0;
  110     /*const char *real_error_str = NULL;*/
  111 
  112     PGconn *conn = db->handle;
  113 
  114     if (PQstatus(conn) != CONNECTION_OK) {
  115         return LOGSQL_QUERY_NOLINK;
  116     }
  117     /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
  118     /* Does postgresql do this also ??? */
  119     handler = signal(SIGPIPE, SIG_IGN);
  120     
  121     result = PQexec(conn, query);
  122     /* Run the query */
  123     if (PQresultStatus(result) == PGRES_COMMAND_OK) {
  124         signal(SIGPIPE, handler);
  125         PQclear(result);
  126         return LOGSQL_QUERY_SUCCESS;
  127     }
  128     /* Check to see if the error is "nonexistent table" */
  129     /*  removed ... don't know how ! (sorry)
  130     real_error = mysql_errno(dblink);
  131 
  132     if (real_error == ER_NO_SUCH_TABLE) {
  133         log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query");
  134         signal(SIGPIPE, handler);
  135         PQclear(result);
  136         return LOGSQL_QUERY_NOTABLE;
  137     }*/
  138     
  139     /* Restore SIGPIPE to its original handler function */
  140     signal(SIGPIPE, handler);
  141     PQclear(result);
  142     return LOGSQL_QUERY_FAIL;
  143 }
  144 
  145 /* Create table table_name of type table_type. */
  146 static logsql_table_ret log_sql_pgsql_create(request_rec *r, logsql_dbconnection *db,
  147                         logsql_tabletype table_type, const char *table_name)
  148 {
  149     PGresult *result;
  150     const char *tabletype = apr_table_get(db->parms,"tabletype");
  151     void (*handler) (int);
  152     char *type_suffix = NULL;
  153 
  154     char *create_prefix = "create table if not exists `";
  155     char *create_suffix = NULL;
  156     char *create_sql;
  157 
  158     PGconn *conn = db->handle;
  159 
  160 /*  if (!global_config.createtables) {
  161         return APR_SUCCESS;
  162     }*/
  163 
  164     switch (table_type) {
  165     case LOGSQL_TABLE_ACCESS:
  166         create_suffix = 
  167     "` (id char(19),\
  168        agent varchar(255),\
  169        bytes_sent int unsigned,\
  170        child_pid smallint unsigned,\
  171        cookie varchar(255),\
  172        machine_id varchar(25),\
  173        request_file varchar(255),\
  174        referer varchar(255),\
  175        remote_host varchar(50),\
  176        remote_logname varchar(50),\
  177        remote_user varchar(50),\
  178        request_duration smallint unsigned,\
  179        request_line varchar(255),\
  180        request_method varchar(10),\
  181        request_protocol varchar(10),\
  182        request_time char(28),\
  183        request_uri varchar(255),\
  184        request_args varchar(255),\
  185        server_port smallint unsigned,\
  186        ssl_cipher varchar(25),\
  187        ssl_keysize smallint unsigned,\
  188        ssl_maxkeysize smallint unsigned,\
  189        status smallint unsigned,\
  190        time_stamp int unsigned,\
  191        virtual_host varchar(255))";
  192         break;
  193     case LOGSQL_TABLE_COOKIES:
  194     case LOGSQL_TABLE_HEADERSIN:
  195     case LOGSQL_TABLE_HEADERSOUT:
  196     case LOGSQL_TABLE_NOTES:
  197         create_suffix = 
  198     "` (id char(19),\
  199        item varchar(80),\
  200        val varchar(80))";
  201         break;
  202     }
  203     
  204     if (tabletype) {
  205         type_suffix = apr_pstrcat(r->pool, " TYPE=", 
  206                             tabletype, NULL);
  207     }
  208     /* Find memory long enough to hold the whole CREATE string + \0 */
  209     create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix,
  210                         type_suffix, NULL);
  211 
  212     log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql);
  213 
  214     if (PQstatus(conn) != CONNECTION_OK) {
  215         return LOGSQL_QUERY_NOLINK;
  216     }
  217     /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
  218     handler = signal(SIGPIPE, SIG_IGN);
  219 
  220     /* Run the create query */
  221     result = PQexec(conn, create_sql);
  222     if (PQresultStatus(result) != PGRES_COMMAND_OK) {
  223         log_error(APLOG_MARK,APLOG_ERR,0, r->server,"failed to create table: %s",
  224             table_name);
  225         signal(SIGPIPE, handler);
  226         PQclear(result);
  227         return LOGSQL_TABLE_FAIL;
  228     }
  229     signal(SIGPIPE, handler);
  230     PQclear(result);
  231     return LOGSQL_TABLE_SUCCESS;
  232 }
  233 
  234 static char *supported_drivers[] = {"pgsql",NULL};
  235 static logsql_dbdriver pgsql_driver = {
  236     supported_drivers,
  237     log_sql_pgsql_connect,  /* open DB connection */
  238     log_sql_pgsql_close,    /* close DB connection */
  239     log_sql_pgsql_escape,   /* escape query */
  240     log_sql_pgsql_query,    /* insert query */
  241     log_sql_pgsql_create    /* create table */
  242 };
  243 
  244 LOGSQL_REGISTER(pgsql) {
  245     log_sql_register_driver(p,&pgsql_driver);
  246     LOGSQL_REGISTER_RETURN;
  247 }