"Fossies" - the Fresh Open Source Software Archive

Member "mod_log_sql-1.101/mod_log_sql_mysql.c" (7 Nov 2006, 7919 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_mysql.c": 1.100_vs_1.101.

    1 /* $Id: mod_log_sql_mysql.c 169 2006-11-07 02:31:10Z 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 #ifdef HAVE_CONFIG_H
   12 /* Undefine these to prevent conflicts between Apache ap_config_auto.h and
   13  * my config.h. Only really needed for Apache < 2.0.48, but it can't hurt.
   14  */
   15 #undef PACKAGE_BUGREPORT
   16 #undef PACKAGE_NAME
   17 #undef PACKAGE_STRING
   18 #undef PACKAGE_TARNAME
   19 #undef PACKAGE_VERSION
   20 
   21 #include "config.h"
   22 #endif
   23 
   24 #include "mod_log_sql.h"
   25 
   26 #include "mysql.h"
   27 #include "mysqld_error.h"
   28 
   29 /* The enduser won't modify these */
   30 #define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away")
   31 
   32 /* Connect to the MYSQL database */
   33 static logsql_opendb_ret log_sql_mysql_connect(server_rec *s, logsql_dbconnection *db)
   34 {
   35     const char *host = apr_table_get(db->parms,"hostname");
   36     const char *user = apr_table_get(db->parms,"username");
   37     const char *passwd = apr_table_get(db->parms,"password");
   38     const char *database = apr_table_get(db->parms,"database");
   39     const char *s_tcpport = apr_table_get(db->parms,"port");
   40     unsigned int tcpport = (s_tcpport)?atoi(s_tcpport):3306;
   41     const char *socketfile = apr_table_get(db->parms,"socketfile");
   42     MYSQL *dblink = db->handle;
   43 
   44     dblink = mysql_init(dblink);
   45     db->handle = (void *)dblink;
   46 
   47 
   48     if (!socketfile) {
   49         socketfile = "/var/lib/mysql/mysql.sock";
   50     }
   51 
   52     if (mysql_real_connect(dblink, host, user, passwd, database, tcpport,
   53                         socketfile, 0)) {
   54         log_error(APLOG_MARK,APLOG_DEBUG,0, s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'",
   55                 host, tcpport, database, user, socketfile);
   56         return LOGSQL_OPENDB_SUCCESS;
   57     } else {
   58         log_error(APLOG_MARK,APLOG_ERR,0, s,"mod_log_sql_mysql: database connection error: mysql error: %s",
   59                 MYSQL_ERROR(dblink));
   60         log_error(APLOG_MARK,APLOG_DEBUG, 0, s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'",
   61                 host, tcpport, database, user, socketfile);
   62         return LOGSQL_OPENDB_FAIL;
   63     }
   64 }
   65 
   66 /* Close the DB link */
   67 static void log_sql_mysql_close(logsql_dbconnection *db)
   68 {
   69     mysql_close((MYSQL *)db->handle);
   70         /* mysql_close frees this data so NULL it out incase we reconnect later */
   71         db->handle=NULL;
   72 }
   73 
   74 /* Routine to escape the 'dangerous' characters that would otherwise
   75  * corrupt the INSERT string: ', \, and "
   76  */
   77 static const char *log_sql_mysql_escape(const char *from_str, apr_pool_t *p,
   78                                 logsql_dbconnection *db)
   79 {
   80         /* Return "NULL" for empty strings */
   81     if (!from_str || strlen(from_str) == 0)
   82         return "NULL";
   83     else {
   84         char *to_str;
   85         unsigned long length = strlen(from_str);
   86         unsigned long retval;
   87 
   88         /* Pre-allocate a new string that could hold twice the original, which would only
   89          * happen if the whole original string was 'dangerous' characters.
   90          */
   91         to_str = (char *) apr_palloc(p, length * 2 + 3);
   92         if (!to_str) {
   93             return from_str;
   94         }
   95         strcpy(to_str, "'");
   96         if (!db->connected) {
   97             /* Well, I would have liked to use the current database charset.  mysql is
   98              * unavailable, however, so I fall back to the slightly less respectful
   99              * mysql_escape_string() function that uses the default charset.
  100              */
  101             retval = mysql_escape_string(to_str+1, from_str, length);
  102         } else {
  103             /* MySQL is available, so I'll go ahead and respect the current charset when
  104              * I perform the escape.
  105              */
  106             retval = mysql_real_escape_string((MYSQL *)db->handle, to_str+1, from_str, length);
  107         }
  108         strcat(to_str,"'");
  109 
  110         if (retval)
  111           return to_str;
  112         else
  113           return from_str;
  114     }
  115 }
  116 
  117 #if defined(WIN32)
  118 #define SIGNAL_GRAB
  119 #define SIGNAL_RELEASE
  120 #define SIGNAL_VAR
  121 #else
  122 #define SIGNAL_VAR void (*handler) (int);
  123 #define SIGNAL_GRAB handler = signal(SIGPIPE, SIG_IGN);
  124 #define SIGNAL_RELEASE signal(SIGPIPE, handler);
  125 #endif
  126 /* Run a mysql insert query and return a categorized error or success */
  127 static logsql_query_ret log_sql_mysql_query(request_rec *r,logsql_dbconnection *db,
  128                                 const char *query)
  129 {
  130     int retval;
  131     SIGNAL_VAR
  132 
  133     unsigned int real_error = 0;
  134     /*const char *real_error_str = NULL;*/
  135 
  136     MYSQL *dblink = (MYSQL *)db->handle;
  137 
  138     if (!dblink) {
  139         return LOGSQL_QUERY_NOLINK;
  140     }
  141 
  142     /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
  143     SIGNAL_GRAB
  144 
  145     /* Run the query */
  146     if (!(retval = mysql_query(dblink, query))) {
  147             SIGNAL_RELEASE
  148         return LOGSQL_QUERY_SUCCESS;
  149     }
  150         log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
  151             "mysql_query returned (%d)", retval);
  152     /* Check to see if the error is "nonexistent table" */
  153     real_error = mysql_errno(dblink);
  154 
  155     if (real_error == ER_NO_SUCH_TABLE) {
  156         log_error(APLOG_MARK,APLOG_ERR,0, r->server,"table does not exist, preserving query");
  157         /* Restore SIGPIPE to its original handler function */
  158         SIGNAL_RELEASE
  159         return LOGSQL_QUERY_NOTABLE;
  160     }
  161 
  162     /* Restore SIGPIPE to its original handler function */
  163     SIGNAL_RELEASE
  164     return LOGSQL_QUERY_FAIL;
  165 }
  166 
  167 /* Create table table_name of type table_type. */
  168 static logsql_table_ret log_sql_mysql_create(request_rec *r, logsql_dbconnection *db,
  169                         logsql_tabletype table_type, const char *table_name)
  170 {
  171     int retval;
  172     const char *tabletype = apr_table_get(db->parms,"tabletype");
  173     SIGNAL_VAR
  174     char *type_suffix = NULL;
  175 
  176     char *create_prefix = "create table if not exists `";
  177     char *create_suffix = NULL;
  178     char *create_sql;
  179 
  180     MYSQL *dblink = (MYSQL *)db->handle;
  181 
  182 /*  if (!global_config.createtables) {
  183         return APR_SUCCESS;
  184     }*/
  185 
  186     switch (table_type) {
  187     case LOGSQL_TABLE_ACCESS:
  188         create_suffix =
  189     "` (id char(19),\
  190        agent varchar(255),\
  191        bytes_sent int unsigned,\
  192        child_pid smallint unsigned,\
  193        cookie varchar(255),\
  194        machine_id varchar(25),\
  195        request_file varchar(255),\
  196        referer varchar(255),\
  197        remote_host varchar(50),\
  198        remote_logname varchar(50),\
  199        remote_user varchar(50),\
  200        request_duration smallint unsigned,\
  201        request_line varchar(255),\
  202        request_method varchar(10),\
  203        request_protocol varchar(10),\
  204        request_time char(28),\
  205        request_uri varchar(255),\
  206        request_args varchar(255),\
  207        server_port smallint unsigned,\
  208        ssl_cipher varchar(25),\
  209        ssl_keysize smallint unsigned,\
  210        ssl_maxkeysize smallint unsigned,\
  211        status smallint unsigned,\
  212        time_stamp int unsigned,\
  213        virtual_host varchar(255),\
  214        bytes_in int unsigned,\
  215        bytes_out int unsigned)";
  216         break;
  217     case LOGSQL_TABLE_COOKIES:
  218     case LOGSQL_TABLE_HEADERSIN:
  219     case LOGSQL_TABLE_HEADERSOUT:
  220     case LOGSQL_TABLE_NOTES:
  221         create_suffix =
  222     "` (id char(19),\
  223        item varchar(80),\
  224        val varchar(80))";
  225         break;
  226     }
  227 
  228     if (tabletype) {
  229         type_suffix = apr_pstrcat(r->pool, " TYPE=",
  230                             tabletype, NULL);
  231     }
  232     /* Find memory long enough to hold the whole CREATE string + \0 */
  233     create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix,
  234                         type_suffix, NULL);
  235 
  236     log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql);
  237 
  238     if (!dblink) {
  239         return LOGSQL_QUERY_NOLINK;
  240     }
  241     /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
  242     SIGNAL_GRAB
  243 
  244     /* Run the create query */
  245     if ((retval = mysql_query(dblink, create_sql))) {
  246         log_error(APLOG_MARK,APLOG_ERR,0, r->server,"failed to create table: %s",
  247             table_name);
  248         SIGNAL_RELEASE
  249         return LOGSQL_TABLE_FAIL;
  250     }
  251     SIGNAL_RELEASE
  252     return LOGSQL_TABLE_SUCCESS;
  253 }
  254 
  255 static const char *supported_drivers[] = {"mysql",NULL};
  256 static logsql_dbdriver mysql_driver = {
  257     "mysql",
  258     supported_drivers,
  259     log_sql_mysql_connect,  /* open DB connection */
  260     log_sql_mysql_close,    /* close DB connection */
  261     log_sql_mysql_escape,   /* escape query */
  262     log_sql_mysql_query,    /* insert query */
  263     log_sql_mysql_create    /* create table */
  264 };
  265 
  266 LOGSQL_REGISTER(mysql) {
  267     log_sql_register_driver(p,&mysql_driver);
  268     LOGSQL_REGISTER_RETURN;
  269 }