"Fossies" - the Fresh Open Source Software Archive 
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 }