summaryrefslogtreecommitdiffstats
path: root/mod_log_sql_pgsql.c
diff options
context:
space:
mode:
Diffstat (limited to 'mod_log_sql_pgsql.c')
-rw-r--r--mod_log_sql_pgsql.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/mod_log_sql_pgsql.c b/mod_log_sql_pgsql.c
new file mode 100644
index 0000000..8fb0f9e
--- /dev/null
+++ b/mod_log_sql_pgsql.c
@@ -0,0 +1,243 @@
1/* $Id$ */
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/* Connect to the MYSQL database */
27static logsql_opendb_ret log_sql_pgsql_connect(server_rec *s, logsql_dbconnection *db)
28{
29 const char *host = apr_table_get(db->parms,"hostname");
30 const char *user = apr_table_get(db->parms,"username");
31 const char *passwd = apr_table_get(db->parms,"password");
32 const char *database = apr_table_get(db->parms,"database");
33 const char *s_tcpport = apr_table_get(db->parms,"port");
34 unsigned int tcpport = (s_tcpport)?atoi(s_tcpport):3306;
35 const char *socketfile = apr_table_get(db->parms,"socketfile");
36 MYSQL *dblink = db->handle;
37
38 dblink = mysql_init(dblink);
39 db->handle = (void *)dblink;
40
41
42 if (!socketfile) {
43 socketfile = "/var/lib/mysql/mysql.sock";
44 }
45
46 if (mysql_real_connect(dblink, host, user, passwd, database, tcpport,
47 socketfile, 0)) {
48 log_error(APLOG_MARK,APLOG_DEBUG,0, s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'",
49 host, tcpport, database, user, socketfile);
50 return LOGSQL_OPENDB_SUCCESS;
51 } else {
52 log_error(APLOG_MARK,APLOG_DEBUG,0, s,"mod_log_sql: database connection error: %s",
53 MYSQL_ERROR(dblink));
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_FAIL;
57 }
58}
59
60/* Close the DB link */
61static void log_sql_pgsql_close(logsql_dbconnection *db)
62{
63 mysql_close((MYSQL *)db->handle);
64}
65
66/* Routine to escape the 'dangerous' characters that would otherwise
67 * corrupt the INSERT string: ', \, and "
68 */
69static const char *log_sql_pgsql_escape(const char *from_str, apr_pool_t *p,
70 logsql_dbconnection *db)
71{
72 if (!from_str)
73 return NULL;
74 else {
75 char *to_str;
76 unsigned long length = strlen(from_str);
77 unsigned long retval;
78
79 /* Pre-allocate a new string that could hold twice the original, which would only
80 * happen if the whole original string was 'dangerous' characters.
81 */
82 to_str = (char *) apr_palloc(p, length * 2 + 1);
83 if (!to_str) {
84 return from_str;
85 }
86
87 if (!db->connected) {
88 /* Well, I would have liked to use the current database charset. mysql is
89 * unavailable, however, so I fall back to the slightly less respectful
90 * mysql_escape_string() function that uses the default charset.
91 */
92 retval = mysql_escape_string(to_str, from_str, length);
93 } else {
94 /* MySQL is available, so I'll go ahead and respect the current charset when
95 * I perform the escape.
96 */
97 retval = mysql_real_escape_string((MYSQL *)db->handle, to_str, from_str, length);
98 }
99
100 if (retval)
101 return to_str;
102 else
103 return from_str;
104 }
105}
106
107/* Run a mysql insert query and return a categorized error or success */
108static logsql_query_ret log_sql_pgsql_query(request_rec *r,logsql_dbconnection *db,
109 const char *query)
110{
111 int retval;
112 void (*handler) (int);
113 unsigned int real_error = 0;
114 /*const char *real_error_str = NULL;*/
115
116 MYSQL *dblink = (MYSQL *)db->handle;
117
118 if (!dblink) {
119 return LOGSQL_QUERY_NOLINK;
120 }
121 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
122 handler = signal(SIGPIPE, SIG_IGN);
123
124 /* Run the query */
125 if (!(retval = mysql_query(dblink, query))) {
126 signal(SIGPIPE, handler);
127 return LOGSQL_QUERY_SUCCESS;
128 }
129 /* Check to see if the error is "nonexistent table" */
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 /* Restore SIGPIPE to its original handler function */
135 signal(SIGPIPE, handler);
136 return LOGSQL_QUERY_NOTABLE;
137 }
138
139 /* Restore SIGPIPE to its original handler function */
140 signal(SIGPIPE, handler);
141 return LOGSQL_QUERY_FAIL;
142}
143
144/* Create table table_name of type table_type. */
145static logsql_table_ret log_sql_pgsql_create(request_rec *r, logsql_dbconnection *db,
146 logsql_tabletype table_type, const char *table_name)
147{
148 int retval;
149 const char *tabletype = apr_table_get(db->parms,"tabletype");
150 void (*handler) (int);
151 char *type_suffix = NULL;
152
153 char *create_prefix = "create table if not exists `";
154 char *create_suffix = NULL;
155 char *create_sql;
156
157 MYSQL *dblink = (MYSQL *)db->handle;
158
159/* if (!global_config.createtables) {
160 return APR_SUCCESS;
161 }*/
162
163 switch (table_type) {
164 case LOGSQL_TABLE_ACCESS:
165 create_suffix =
166 "` (id char(19),\
167 agent varchar(255),\
168 bytes_sent int unsigned,\
169 child_pid smallint unsigned,\
170 cookie varchar(255),\
171 machine_id varchar(25),\
172 request_file varchar(255),\
173 referer varchar(255),\
174 remote_host varchar(50),\
175 remote_logname varchar(50),\
176 remote_user varchar(50),\
177 request_duration smallint unsigned,\
178 request_line varchar(255),\
179 request_method varchar(10),\
180 request_protocol varchar(10),\
181 request_time char(28),\
182 request_uri varchar(255),\
183 request_args varchar(255),\
184 server_port smallint unsigned,\
185 ssl_cipher varchar(25),\
186 ssl_keysize smallint unsigned,\
187 ssl_maxkeysize smallint unsigned,\
188 status smallint unsigned,\
189 time_stamp int unsigned,\
190 virtual_host varchar(255))";
191 break;
192 case LOGSQL_TABLE_COOKIES:
193 case LOGSQL_TABLE_HEADERSIN:
194 case LOGSQL_TABLE_HEADERSOUT:
195 case LOGSQL_TABLE_NOTES:
196 create_suffix =
197 "` (id char(19),\
198 item varchar(80),\
199 val varchar(80))";
200 break;
201 }
202
203 if (tabletype) {
204 type_suffix = apr_pstrcat(r->pool, " TYPE=",
205 tabletype, NULL);
206 }
207 /* Find memory long enough to hold the whole CREATE string + \0 */
208 create_sql = apr_pstrcat(r->pool, create_prefix, table_name, create_suffix,
209 type_suffix, NULL);
210
211 log_error(APLOG_MARK,APLOG_DEBUG,0, r->server,"create string: %s", create_sql);
212
213 if (!dblink) {
214 return LOGSQL_QUERY_NOLINK;
215 }
216 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
217 handler = signal(SIGPIPE, SIG_IGN);
218
219 /* Run the create query */
220 if ((retval = mysql_query(dblink, create_sql))) {
221 log_error(APLOG_MARK,APLOG_ERR,0, r->server,"failed to create table: %s",
222 table_name);
223 signal(SIGPIPE, handler);
224 return LOGSQL_TABLE_FAIL;
225 }
226 signal(SIGPIPE, handler);
227 return LOGSQL_TABLE_SUCCESS;
228}
229
230static char *supported_drivers[] = {"pgsql",NULL};
231static logsql_dbdriver pgsql_driver = {
232 supported_drivers,
233 log_sql_mysql_connect, /* open DB connection */
234 log_sql_mysql_close, /* close DB connection */
235 log_sql_mysql_escape, /* escape query */
236 log_sql_mysql_query, /* insert query */
237 log_sql_mysql_create /* create table */
238};
239
240LOGSQL_REGISTER(pgsql) {
241 log_sql_register_driver(p,&pgsql_driver);
242 LOGSQL_REGISTER_RETURN;
243}