]> jfr.im git - irc/evilnet/x3.git/blame - patches/log-pgsql.diff
Fixed LDAP support to register an account with X3 if a user is authed to that account...
[irc/evilnet/x3.git] / patches / log-pgsql.diff
CommitLineData
d76ed9a9 1Index: src/Makefile.am
2===================================================================
3RCS file: /cvsroot/srvx/services/src/Makefile.am,v
4retrieving revision 1.59
5diff -u -r1.59 Makefile.am
6--- src/Makefile.am 9 Sep 2003 01:56:55 -0000 1.59
7+++ src/Makefile.am 28 Sep 2003 14:16:39 -0000
8@@ -9,7 +9,7 @@
9 ./expnhelp < $(srcdir)/nickserv.help.m4 > $@
10
7827220c 11 EXTRA_srvx_SOURCES = proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c
d76ed9a9 12-srvx_LDADD = @MODULE_OBJS@
13+srvx_LDADD = @MODULE_OBJS@ -lpq
14 srvx_DEPENDENCIES = @MODULE_OBJS@
15 srvx_SOURCES = \
16 chanserv.c chanserv.h \
17Index: src/log.c
18===================================================================
19RCS file: /cvsroot/srvx/services/src/log.c,v
20retrieving revision 1.65
21diff -u -r1.65 log.c
22--- src/log.c 22 Aug 2003 00:26:21 -0000 1.65
23+++ src/log.c 28 Sep 2003 14:16:40 -0000
24@@ -22,6 +22,8 @@
25 #include "log.h"
26 #include "helpfile.h"
27 #include "nickserv.h"
28+#include "ioset.h"
29+#include <postgresql/libpq-fe.h>
30
31 struct logDestination;
32
33@@ -992,6 +994,234 @@
34 ldIrc_module
35 };
36
37+/* pgsql: log type */
38+
39+struct logDest_pgsql {
40+ struct logDestination base;
41+ struct string_list queue;
42+ PGconn *conn;
43+ struct io_fd *fd;
44+ int recurse_level;
45+};
46+static struct logDest_vtable ldPgsql_vtbl;
47+
48+static void ldPgsql_send_next_query(struct logDest_pgsql *ld) {
49+ int res;
50+
51+ res = PQsendQuery(ld->conn, ld->queue.list[0]);
52+ if (!res) {
53+ ld->recurse_level++;
54+ log_module(MAIN_LOG, LOG_ERROR, "Error sending query \"%s\": %s", ld->queue.list[0], PQerrorMessage(ld->conn));
55+ ld->recurse_level--;
56+ return;
57+ }
58+ res = PQflush(ld->conn);
59+ if (res == EOF) {
60+ ld->recurse_level++;
61+ log_module(MAIN_LOG, LOG_ERROR, "Error flushing PgSql output: %s", PQerrorMessage(ld->conn));
62+ ld->recurse_level--;
63+ }
64+}
65+
66+static void ldPgsql_readable(struct io_fd *fd) {
67+ struct logDest_pgsql *ld = fd->data;
68+ PGresult *pgres;
69+ unsigned int ii;
70+ int res;
71+ ExecStatusType st;
72+
73+ res = PQconsumeInput(ld->conn);
74+ if (!res) {
75+ ld->recurse_level++;
76+ log_module(MAIN_LOG, LOG_ERROR, "Error consuming PgSql input: %s", PQerrorMessage(ld->conn));
77+ ld->recurse_level--;
78+ }
79+ if (PQisBusy(ld->conn))
80+ return;
81+ while ((pgres = PQgetResult(ld->conn))) {
82+ st = PQresultStatus(pgres);
83+ if (st != PGRES_COMMAND_OK) {
84+ ld->recurse_level++;
85+ log_module(MAIN_LOG, LOG_ERROR, "PgSql error in \"%s\": %s", ld->queue.list[0], PQresultErrorMessage(pgres));
86+ ld->recurse_level--;
87+ }
88+ PQclear(pgres);
89+ }
90+ if (ld->queue.used == 1)
91+ ld->queue.list[1] = NULL;
92+ free(ld->queue.list[0]);
93+ ld->queue.used--;
94+ for (ii = 0; ii < ld->queue.used; ++ii)
95+ ld->queue.list[ii] = ld->queue.list[ii+1];
96+ if (ld->queue.used)
97+ ldPgsql_send_next_query(ld);
98+}
99+
100+static struct logDestination *
101+ldPgsql_open(const char *args) {
102+ struct logDest_pgsql *ld;
103+ ld = calloc(1, sizeof(*ld));
104+ ld->base.vtbl = &ldPgsql_vtbl;
105+ ld->conn = PQconnectdb(args);
106+ ld->recurse_level++;
107+ if (!ld->conn) {
108+ log_module(MAIN_LOG, LOG_ERROR, "Unable to allocate pgsql connection");
109+ } else if (PQstatus(ld->conn) == CONNECTION_BAD) {
110+ log_module(MAIN_LOG, LOG_ERROR, "Pgsql connection failed: %s", PQerrorMessage(ld->conn));
111+ } else {
112+ int res;
113+ res = PQsetnonblocking(ld->conn, 1);
114+ if (res == -1)
115+ log_module(MAIN_LOG, LOG_ERROR, "Unable to make pgsql non-blocking");
116+ ld->fd = ioset_add(PQsocket(ld->conn));
117+ ld->fd->data = ld;
118+ ld->fd->connected = 1;
119+ ld->fd->wants_reads = 1;
120+ ld->fd->readable_cb = ldPgsql_readable;
121+ while (PQflush(ld->conn)) ;
122+ }
123+ ld->recurse_level--;
124+ return &ld->base;
125+}
126+
127+static void
128+ldPgsql_reopen(struct logDestination *self_) {
129+ struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
130+ PQreset(self->conn);
131+}
132+
133+static void
134+ldPgsql_close(struct logDestination *self_) {
135+ struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
136+ unsigned int ii;
137+
138+ PQfinish(self->conn);
139+ ioset_close(self->fd->fd, 0);
140+ for (ii = 0; ii < self->queue.used; ++ii)
141+ free(self->queue.list[ii]);
142+ self->recurse_level--;
143+ free(self->queue.list);
144+ free(self);
145+}
146+
147+static void
148+string_buffer_append_quoted(struct string_buffer *dest, const char *src) {
149+ size_t len = strlen(src);
150+ if (dest->size < dest->used + len * 2) {
151+ if (dest->size < len * 2) {
152+ dest->size = len * 4;
153+ } else {
154+ dest->size = dest->size * 2;
155+ }
156+ dest->list = realloc(dest->list, dest->size);
157+ }
158+ dest->used += PQescapeString(dest->list+dest->used, src, len);
159+}
160+
161+static void
162+string_buffer_append_time(struct string_buffer *dest, time_t when) {
163+ struct tm gmt;
164+ if (dest->size < dest->used + 20) {
165+ if (dest->size < 20) {
166+ dest->size = 40;
167+ } else {
168+ dest->size = dest->size * 2;
169+ }
170+ dest->list = realloc(dest->list, dest->size);
171+ }
172+ dest->used += strftime(dest->list + dest->used, dest->size - dest->used, "%Y-%m-%d %H:%M:%S", gmtime_r(&when, &gmt));
173+}
174+
175+static void
176+string_buffer_append_quoted2(struct string_buffer *dest, const char *src) {
177+ if (src) {
178+ string_buffer_append_string(dest, ", '");
179+ string_buffer_append_quoted(dest, src);
180+ string_buffer_append(dest, '\'');
181+ } else {
182+ string_buffer_append_string(dest, ", NULL");
183+ }
184+}
185+
186+static void
187+pgsql_insert(struct logDest_pgsql *self, char *query) {
188+ string_list_append(&self->queue, query);
189+ if (self->queue.used == 1)
190+ ldPgsql_send_next_query(self);
191+}
192+
193+static void
194+ldPgsql_audit(struct logDestination *self_, struct log_type *type, struct logEntry *entry) {
195+ struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
196+ struct string_buffer query;
197+
198+ if (self->recurse_level)
199+ return;
200+ query.size = 512;
201+ query.list = malloc(query.size);
202+ query.used = 0;
203+ string_buffer_append_printf(&query, "INSERT INTO srvx_audit (i_module, i_severity, i_bot, t_when, c_channel_name, c_user_nick, c_user_account, c_user_hostmask, c_command) VALUES (srvx_module_id('");
204+ string_buffer_append_quoted(&query, type->name);
205+ string_buffer_append_printf(&query, "'), %d, srvx_bot_id('", entry->slvl);
206+ string_buffer_append_quoted(&query, entry->bot->nick);
207+ string_buffer_append_string(&query, "'), '");
208+ string_buffer_append_time(&query, entry->time);
209+ string_buffer_append_string(&query, "'");
210+ string_buffer_append_quoted2(&query, entry->channel_name);
211+ string_buffer_append_quoted2(&query, entry->user_nick);
212+ string_buffer_append_quoted2(&query, entry->user_account);
213+ string_buffer_append_quoted2(&query, entry->user_hostmask);
214+ string_buffer_append_quoted2(&query, entry->command);
215+ string_buffer_append_string(&query, ");");
216+ pgsql_insert(self, query.list);
217+}
218+
219+static void
220+ldPgsql_replay(struct logDestination *self_, struct log_type *type, int is_write, const char *line) {
221+ struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
222+ struct string_buffer query;
223+
224+ if (self->recurse_level)
225+ return;
226+ query.size = 512;
227+ query.list = malloc(query.size);
228+ query.used = 0;
229+ string_buffer_append_printf(&query, "INSERT INTO srvx_replay (i_module, b_is_write, c_text) VALUES (srvx_module_id('");
230+ string_buffer_append_quoted(&query, type->name);
231+ string_buffer_append_printf(&query, "'), %s, '", (is_write ? "true" : "false"));
232+ string_buffer_append_quoted(&query, line);
233+ string_buffer_append_string(&query, "');");
234+ pgsql_insert(self, query.list);
235+}
236+
237+static void
238+ldPgsql_module(struct logDestination *self_, struct log_type *type, enum log_severity sev, const char *message) {
239+ struct logDest_pgsql *self = (struct logDest_pgsql*)self_;
240+ struct string_buffer query;
241+
242+ if (self->recurse_level)
243+ return;
244+ query.size = 512;
245+ query.list = malloc(query.size);
246+ query.used = 0;
247+ string_buffer_append_printf(&query, "INSERT INTO srvx_log (i_module, i_severity, c_message) VALUES (srvx_module_id('");
248+ string_buffer_append_quoted(&query, type->name);
249+ string_buffer_append_printf(&query, "'), %d, '", sev);
250+ string_buffer_append_quoted(&query, message);
251+ string_buffer_append_string(&query, "');");
252+ pgsql_insert(self, query.list);
253+}
254+
255+static struct logDest_vtable ldPgsql_vtbl = {
256+ "pgsql",
257+ ldPgsql_open,
258+ ldPgsql_reopen,
259+ ldPgsql_close,
260+ ldPgsql_audit,
261+ ldPgsql_replay,
262+ ldPgsql_module
263+};
264+
265 void
266 log_init(void)
267 {
268@@ -1003,6 +1233,7 @@
269 dict_insert(log_dest_types, ldFile_vtbl.type_name, &ldFile_vtbl);
270 dict_insert(log_dest_types, ldStd_vtbl.type_name, &ldStd_vtbl);
271 dict_insert(log_dest_types, ldIrc_vtbl.type_name, &ldIrc_vtbl);
272+ dict_insert(log_dest_types, ldPgsql_vtbl.type_name, &ldPgsql_vtbl);
273 conf_register_reload(log_conf_read);
274 log_default = log_register_type("*", NULL);
275 reg_exit_func(cleanup_logs);