]> jfr.im git - irc/evilnet/x3.git/blob - patches/helpserv-pgsql.diff
Fix for issue with SASL account names
[irc/evilnet/x3.git] / patches / helpserv-pgsql.diff
1 Index: src/Makefile.am
2 ===================================================================
3 RCS file: /cvsroot/srvx/services/src/Makefile.am,v
4 retrieving revision 1.59
5 diff -u -r1.59 Makefile.am
6 --- src/Makefile.am 9 Sep 2003 01:56:55 -0000 1.59
7 +++ src/Makefile.am 5 Nov 2003 14:15:46 -0000
8 @@ -9,7 +9,7 @@
9 ./expnhelp < $(srcdir)/nickserv.help.m4 > $@
10
11 EXTRA_srvx_SOURCES = proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c
12 -srvx_LDADD = @MODULE_OBJS@
13 +srvx_LDADD = @MODULE_OBJS@ -lpq
14 srvx_DEPENDENCIES = @MODULE_OBJS@
15 srvx_SOURCES = \
16 chanserv.c chanserv.h \
17 Index: src/helpserv.c
18 ===================================================================
19 RCS file: /cvsroot/srvx/services/src/helpserv.c,v
20 retrieving revision 1.84
21 diff -u -r1.84 helpserv.c
22 --- src/helpserv.c 5 Nov 2003 13:52:23 -0000 1.84
23 +++ src/helpserv.c 5 Nov 2003 14:15:48 -0000
24 @@ -46,6 +46,8 @@
25 #include "opserv.h"
26 #include "saxdb.h"
27 #include "timeq.h"
28 +#include "ioset.h"
29 +#include <postgresql/libpq-fe.h>
30
31 #define HELPSERV_CONF_NAME "services/helpserv"
32 #define HELPSERV_HELPFILE_NAME "helpserv.help"
33 @@ -94,6 +96,7 @@
34 #define KEY_REQ_ON_JOIN "req_on_join"
35 #define KEY_AUTO_VOICE "auto_voice"
36 #define KEY_AUTO_DEVOICE "auto_devoice"
37 +#define KEY_LOG_SQL "log_sql"
38
39 /* General */
40 #define HSMSG_WRITE_SUCCESS "HelpServ db write completed (in "FMT_TIME_T".%03lu seconds)."
41 @@ -401,6 +404,7 @@
42 const char *description;
43 unsigned long db_backup_frequency;
44 const char *reqlogfile;
45 + PGconn *sql_log;
46 } helpserv_conf;
47
48 static int helpserv_enabled;
49 @@ -443,6 +447,7 @@
50 unsigned int req_on_join : 1;
51 unsigned int auto_voice : 1;
52 unsigned int auto_devoice : 1;
53 + unsigned int log_sql : 1;
54
55 unsigned int helpchan_empty : 1;
56
57 @@ -608,36 +613,153 @@
58 return dict_find(hs->users, hi->handle, NULL);
59 }
60
61 -static void helpserv_log_request(struct helpserv_request *req, const char *reason) {
62 - char key[27+NICKLEN];
63 - char userhost[USERLEN+HOSTLEN+2];
64 +static struct string_list sql_queue;
65 +static struct io_fd *sql_fd;
66
67 - if (!reqlog_ctx || !req)
68 +static void pgsql_send_next_query() {
69 + int res;
70 +
71 + res = PQsendQuery(helpserv_conf.sql_log, sql_queue.list[0]);
72 + if (!res) {
73 + log_module(MAIN_LOG, LOG_ERROR, "Error sending query \"%s\": %s", sql_queue.list[0], PQerrorMessage(helpserv_conf.sql_log));
74 return;
75 - if (!reason)
76 - reason = "";
77 + }
78 + res = PQflush(helpserv_conf.sql_log);
79 + if (res == EOF)
80 + log_module(MAIN_LOG, LOG_ERROR, "Error flushing PgSql output: %s", PQerrorMessage(helpserv_conf.sql_log));
81 +}
82 +
83 +static void pgsql_readable(UNUSED_ARG(struct io_fd *fd)) {
84 + PGconn *conn;
85 + PGresult *pgres;
86 + unsigned int ii;
87 + int res;
88 + ExecStatusType st;
89 +
90 + conn = helpserv_conf.sql_log;
91 + res = PQconsumeInput(conn);
92 + if (!res)
93 + log_module(MAIN_LOG, LOG_ERROR, "Error consuming PgSql input: %s", PQerrorMessage(conn));
94 + if (PQisBusy(conn))
95 + return;
96 + while ((pgres = PQgetResult(conn))) {
97 + st = PQresultStatus(pgres);
98 + if (st != PGRES_COMMAND_OK)
99 + log_module(MAIN_LOG, LOG_ERROR, "PgSql error in \"%s\": %s", sql_queue.list[0], PQresultErrorMessage(pgres));
100 + PQclear(pgres);
101 + }
102 + if (sql_queue.used == 1)
103 + sql_queue.list[1] = NULL;
104 + free(sql_queue.list[0]);
105 + sql_queue.used--;
106 + for (ii = 0; ii < sql_queue.used; ++ii)
107 + sql_queue.list[ii] = sql_queue.list[ii+1];
108 + if (sql_queue.used)
109 + pgsql_send_next_query();
110 +}
111
112 - sprintf(key, "%s-" FMT_TIME_T "-%lu", req->hs->helpserv->nick, req->opened, req->id);
113 - saxdb_start_record(reqlog_ctx, key, 1);
114 - if (req->helper) {
115 - saxdb_write_string(reqlog_ctx, KEY_REQUEST_HELPER, req->helper->handle->handle);
116 - saxdb_write_int(reqlog_ctx, KEY_REQUEST_ASSIGNED, req->assigned);
117 +static void
118 +string_buffer_append_quoted(struct string_buffer *dest, const char *src) {
119 + if (src) {
120 + size_t len = strlen(src);
121 + string_buffer_append(dest, '\'');
122 + if (dest->size < (dest->used + len * 2)) {
123 + if (dest->size < len * 2)
124 + dest->size = len * 4;
125 + else
126 + dest->size = dest->size * 2;
127 + dest->list = realloc(dest->list, dest->size);
128 + }
129 + dest->used += PQescapeString(dest->list + dest->used, src, len);
130 + string_buffer_append_string(dest, "', ");
131 + } else {
132 + string_buffer_append_string(dest, "NULL, ");
133 }
134 - if (req->handle) {
135 - saxdb_write_string(reqlog_ctx, KEY_REQUEST_HANDLE, req->handle->handle);
136 +}
137 +
138 +static void
139 +string_buffer_append_time(struct string_buffer *dest, time_t when) {
140 + struct tm broken_out;
141 + if (!when) {
142 + string_buffer_append_string(dest, "NULL, ");
143 + return;
144 }
145 - if (req->user) {
146 - saxdb_write_string(reqlog_ctx, KEY_REQUEST_NICK, req->user->nick);
147 - sprintf(userhost, "%s@%s", req->user->ident, req->user->hostname);
148 - saxdb_write_string(reqlog_ctx, KEY_REQUEST_USERHOST, userhost);
149 + if (dest->size < dest->used + 20) {
150 + if (dest->size < 20) {
151 + dest->size = 40;
152 + } else {
153 + dest->size = dest->size * 2;
154 + }
155 + dest->list = realloc(dest->list, dest->size);
156 }
157 - saxdb_write_int(reqlog_ctx, KEY_REQUEST_OPENED, req->opened);
158 - saxdb_write_int(reqlog_ctx, KEY_REQUEST_CLOSED, now);
159 - saxdb_write_string(reqlog_ctx, KEY_REQUEST_CLOSEREASON, reason);
160 - saxdb_write_string_list(reqlog_ctx, KEY_REQUEST_TEXT, req->text);
161 - saxdb_end_record(reqlog_ctx);
162 + dest->used += strftime(dest->list + dest->used, dest->size - dest->used, "'%Y-%m-%d %H:%M:%S', ", localtime_r(&when, &broken_out));
163 +}
164
165 - fflush(reqlog_f);
166 +static void
167 +pgsql_insert(char *query) {
168 + string_list_append(&sql_queue, query);
169 + if (sql_queue.used == 1)
170 + pgsql_send_next_query();
171 +}
172 +
173 +static void helpserv_log_request(struct helpserv_request *req, const char *reason) {
174 + char userhost[USERLEN+HOSTLEN+2];
175 +
176 + if (req->user)
177 + sprintf(userhost, "%s@%s", req->user->ident, req->user->hostname);
178 + else
179 + userhost[0] = 0;
180 + if (reqlog_ctx) {
181 + char key[27+NICKLEN];
182 + sprintf(key, "%s-" FMT_TIME_T "-%lu", req->hs->helpserv->nick, req->opened, req->id);
183 + saxdb_start_record(reqlog_ctx, key, 1);
184 + if (req->helper) {
185 + saxdb_write_string(reqlog_ctx, KEY_REQUEST_HELPER, req->helper->handle->handle);
186 + saxdb_write_int(reqlog_ctx, KEY_REQUEST_ASSIGNED, req->assigned);
187 + }
188 + if (req->handle)
189 + saxdb_write_string(reqlog_ctx, KEY_REQUEST_HANDLE, req->handle->handle);
190 + if (req->user) {
191 + saxdb_write_string(reqlog_ctx, KEY_REQUEST_NICK, req->user->nick);
192 + saxdb_write_string(reqlog_ctx, KEY_REQUEST_USERHOST, userhost);
193 + }
194 + saxdb_write_int(reqlog_ctx, KEY_REQUEST_OPENED, req->opened);
195 + saxdb_write_int(reqlog_ctx, KEY_REQUEST_CLOSED, now);
196 + saxdb_write_string(reqlog_ctx, KEY_REQUEST_CLOSEREASON, reason);
197 + saxdb_write_string_list(reqlog_ctx, KEY_REQUEST_TEXT, req->text);
198 + saxdb_end_record(reqlog_ctx);
199 + fflush(reqlog_f);
200 + }
201 + if (helpserv_conf.sql_log && req->hs->log_sql) {
202 + struct string_buffer query, sb;
203 + unsigned int ii;
204 +
205 + sb.used = query.used = 0;
206 + sb.size = query.size = 512;
207 + query.list = malloc(query.size);
208 + sb.list = malloc(sb.size);
209 + string_buffer_append_string(&query, "INSERT INTO srvx_helpserv_reqs (c_bot, t_opened, t_assigned, t_closed, i_id, c_helper, c_user_account, c_user_nick, c_user_host, c_close_reason, c_text) VALUES (");
210 + string_buffer_append_quoted(&query, req->hs->helpserv->nick);
211 + string_buffer_append_time(&query, req->opened);
212 + string_buffer_append_time(&query, req->assigned);
213 + string_buffer_append_time(&query, now);
214 + string_buffer_append_printf(&query, "%lu, ", req->id);
215 + string_buffer_append_quoted(&query, req->helper ? req->helper->handle->handle : NULL);
216 + string_buffer_append_quoted(&query, req->handle ? req->handle->handle : NULL);
217 + string_buffer_append_quoted(&query, req->user ? req->user->nick : NULL);
218 + string_buffer_append_quoted(&query, req->user ? userhost : NULL);
219 + string_buffer_append_quoted(&query, reason);
220 + for (ii = 0; ii < req->text->used; ++ii) {
221 + string_buffer_append_string(&sb, req->text->list[ii]);
222 + string_buffer_append(&sb, '\n');
223 + }
224 + string_buffer_append(&sb, 0);
225 + string_buffer_append_quoted(&query, sb.list);
226 + query.used -= 2; /* chop off ", " from append_quoted */
227 + string_buffer_append_string(&query, ");");
228 + pgsql_insert(query.list);
229 + free(sb.list);
230 + }
231 }
232
233 /* Searches for a request by number, nick, or account (num|nick|*account).
234 @@ -2931,6 +3053,28 @@
235 OPTION_BINARY(hs->auto_devoice, "AutoDeVoice");
236 }
237
238 +static HELPSERV_OPTION(opt_log_sql) {
239 + int changed = 0;
240 + if (argc > 0) {
241 + if (!from_opserv) {
242 + helpserv_notice(user, HSMSG_SET_NEED_OPER);
243 + return 0;
244 + }
245 + if (enabled_string(argv[0])) {
246 + hs->log_sql = 1;
247 + changed = 1;
248 + } else if (disabled_string(argv[0])) {
249 + hs->log_sql = 0;
250 + changed = 1;
251 + } else {
252 + helpserv_notice(user, MSG_INVALID_BINARY, argv[0]);
253 + return 0;
254 + }
255 + }
256 + helpserv_notice(user, HSMSG_STRING_VALUE, "LogSql", hs->log_sql ? "Enabled" : "Disabled");
257 + return changed;
258 +}
259 +
260 static HELPSERV_FUNC(cmd_set) {
261 helpserv_option_func_t *opt;
262
263 @@ -2944,7 +3088,7 @@
264 opt_empty_interval, opt_stale_delay, opt_request_persistence,
265 opt_helper_persistence, opt_notification, opt_id_wrap,
266 opt_req_maxlen, opt_privmsg_only, opt_req_on_join, opt_auto_voice,
267 - opt_auto_devoice
268 + opt_auto_devoice, opt_log_sql
269 };
270
271 helpserv_notice(user, HSMSG_QUEUE_OPTIONS);
272 @@ -3267,6 +3411,7 @@
273 saxdb_write_int(ctx, KEY_REQ_ON_JOIN, hs->req_on_join);
274 saxdb_write_int(ctx, KEY_AUTO_VOICE, hs->auto_voice);
275 saxdb_write_int(ctx, KEY_AUTO_DEVOICE, hs->auto_devoice);
276 + saxdb_write_int(ctx, KEY_LOG_SQL, hs->log_sql);
277
278 /* End bot record */
279 saxdb_end_record(ctx);
280 @@ -3376,6 +3521,8 @@
281 hs->auto_voice = str ? enabled_string(str) : 0;
282 str = database_get_data(GET_RECORD_OBJECT(br), KEY_AUTO_DEVOICE, RECDB_QSTRING);
283 hs->auto_devoice = str ? enabled_string(str) : 0;
284 + str = database_get_data(GET_RECORD_OBJECT(br), KEY_LOG_SQL, RECDB_QSTRING);
285 + hs->log_sql = str ? enabled_string(str) : 0;
286
287 dict_foreach(users, user_read_helper, hs);
288
289 @@ -3422,6 +3569,31 @@
290 helpserv_conf.reqlogfile = NULL;
291 }
292
293 + if (helpserv_conf.sql_log) {
294 + PQfinish(helpserv_conf.sql_log);
295 + helpserv_conf.sql_log = NULL;
296 + }
297 + str = database_get_data(conf_node, "sql_log", RECDB_QSTRING);
298 + if (str) {
299 + PGconn *conn = PQconnectdb(str);
300 + if (!conn) {
301 + log_module(HS_LOG, LOG_ERROR, "Unable to allocate pgsql connection");
302 + } else if (PQstatus(conn) == CONNECTION_BAD) {
303 + log_module(HS_LOG, LOG_ERROR, "Pgsql connection failed: %s", PQerrorMessage(conn));
304 + PQfinish(conn);
305 + } else if (PQsetnonblocking(conn, 1) == -1) {
306 + log_module(HS_LOG, LOG_ERROR, "Unable to make pgsql non-blocking");
307 + PQfinish(conn);
308 + } else {
309 + helpserv_conf.sql_log = conn;
310 + sql_fd = ioset_add(PQsocket(conn));
311 + sql_fd->connected = 1;
312 + sql_fd->wants_reads = 1;
313 + sql_fd->readable_cb = pgsql_readable;
314 + while (PQflush(conn)) ;
315 + }
316 + }
317 +
318 if (reqlog_ctx) {
319 saxdb_close_context(reqlog_ctx);
320 reqlog_ctx = NULL;
321 @@ -4159,16 +4331,20 @@
322 return mktime(timeinfo);
323 }
324
325 -/* If data != NULL, then don't add to the timeq */
326 static void helpserv_run_stats(time_t when) {
327 struct tm when_s;
328 + struct string_buffer query;
329 struct helpserv_bot *hs;
330 struct helpserv_user *hs_user;
331 int i;
332 dict_iterator_t it, it2;
333 + char timestamp[64];
334
335 last_stats_update = when;
336 localtime_r(&when, &when_s);
337 + strftime(timestamp, sizeof(timestamp), "'%Y-%m-%d %H:%M:%S', ", &when_s);
338 + query.size = 512;
339 +
340 for (it=dict_first(helpserv_bots_dict); it; it=iter_next(it)) {
341 hs = iter_data(it);
342
343 @@ -4195,6 +4371,18 @@
344 hs_user->reassigned_to[i] = hs_user->reassigned_to[i-1];
345 }
346
347 + /* Log to SQL */
348 + if (helpserv_conf.sql_log && hs->log_sql) {
349 + query.list = malloc(query.size);
350 + query.used = 0;
351 + string_buffer_append_string(&query, "INSERT INTO srvx_helpserv_stats (c_bot, t_weekstart, c_helper, i_time, i_picked_up, i_closed, i_reassigned_from, i_reassigned_to) VALUES(");
352 + string_buffer_append_quoted(&query, hs->helpserv->nick);
353 + string_buffer_append_quoted(&query, timestamp);
354 + string_buffer_append_quoted(&query, hs_user->handle->handle);
355 + string_buffer_append_printf(&query, "%d, %d, %d, %d, %d);", hs_user->time_per_week[0], hs_user->picked_up[0], hs_user->closed[0], hs_user->reassigned_from[0], hs_user->reassigned_to[0]);
356 + pgsql_insert(query.list);
357 + }
358 +
359 /* Reset it for this week */
360 hs_user->time_per_week[0] = hs_user->picked_up[0] = hs_user->closed[0] = hs_user->reassigned_from[0] = hs_user->reassigned_to[0] = 0;
361 }
362 @@ -4228,6 +4416,10 @@
363 saxdb_close_context(reqlog_ctx);
364 if (reqlog_f)
365 fclose(reqlog_f);
366 + if (helpserv_conf.sql_log) {
367 + PQfinish(helpserv_conf.sql_log);
368 + helpserv_conf.sql_log = NULL;
369 + }
370 }
371
372 void init_helpserv() {
373 @@ -4293,6 +4485,7 @@
374 helpserv_define_option("REQONJOIN", opt_req_on_join);
375 helpserv_define_option("AUTOVOICE", opt_auto_voice);
376 helpserv_define_option("AUTODEVOICE", opt_auto_devoice);
377 + helpserv_define_option("LOGSQL", opt_log_sql);
378
379 helpserv_bots_dict = dict_new();
380 dict_set_free_data(helpserv_bots_dict, helpserv_free_bot);