]> jfr.im git - irc/thales.git/blame - src/db.c
readmes added, contribs removed
[irc/thales.git] / src / db.c
CommitLineData
2ace9480 1/* Thales - IRC to Relational Database Gateway
2 * Copyright (C) 2002 Lucas Nussbaum <lucas@lucas-nussbaum.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18/* Thales' database interface */
19
20#include "db.h"
21#include "misc.h"
22#include "actions.h"
23#ifdef HASHLISTSUPPORT
24#include "hashlist.h"
25#endif
26
27extern char *MysqlServer;
28extern char *MysqlDatabase;
29extern char *MysqlUser;
30extern char *MysqlPassword;
31
32extern unsigned int nbusers_max;
33extern unsigned int nbusers;
34extern unsigned int nbchans_max;
35extern unsigned int nbchans;
36
37extern int verbose;
38
39MYSQL *myptr;
40
41#ifdef HASHLISTSUPPORT
42hashlist hashnicks;
43hashlist hashchans;
44hashlist hashservs;
45#endif
46
47/* last time we cleaned the server table */
48static int ServerLastClean = -1;
49extern int ServerCleanFreq;
50extern int ServerCacheTime;
51
52/* last time we cleaned the user table */
53static int UserLastClean = -1;
54extern int UserCleanFreq;
55extern int UserCacheTime;
56
57
58void db_connect()
59{
60 MYSQL_RES *resptr;
61 if (myptr)
62 mysql_close(myptr);
63 /* connecting to MySQL */
64 myptr = mysql_init(NULL);
65 if (!mysql_real_connect
66 (myptr, MysqlServer, MysqlUser, MysqlPassword, MysqlDatabase, 0,
67 NULL, 0))
68 fatal("Failed to connect to database : %s\n", mysql_error(myptr));
69
70 /* Cleaning up the database */
71 db_query("DELETE FROM " TBL_CHAN);
72 db_query("DELETE FROM " TBL_ISON);
73 db_query("DELETE FROM " TBL_SERV);
74 db_query("DELETE FROM " TBL_USER);
75
76 db_query("SELECT val FROM " TBL_MAXV " WHERE type=\'users\'");
77 resptr = mysql_store_result(myptr);
78 if (mysql_num_rows(resptr))
79 nbusers_max = atoi(*mysql_fetch_row(resptr));
80 else
81 db_query("INSERT INTO " TBL_MAXV " VALUES ('users', '0', NOW())");
82 mysql_free_result(resptr);
83
84 db_query("SELECT val FROM " TBL_MAXV " WHERE type=\'channels\'");
85 resptr = mysql_store_result(myptr);
86 if (mysql_num_rows(resptr))
87 nbchans_max = atoi(*mysql_fetch_row(resptr));
88 else
89 db_query("INSERT INTO " TBL_MAXV " VALUES ('channels', '0', NOW())");
90 mysql_free_result(resptr);
91
92#ifdef HASHLISTSUPPORT
93 /* init the hash lists */
94 hashnicks = newhashlist();
95 hashchans = newhashlist();
96 hashservs = newhashlist();
97#endif
98}
99
100/* escape the string */
101char *db_escape(char *ch)
102{
103 char *buf = NULL;
104 int size;
105 if (ch)
106 {
107 size = (strlen(ch)) * 2 + 1;
108 buf = (char *) malloc(sizeof(char) * size);
109 if (*ch)
110 mysql_real_escape_string(myptr, buf, ch, strlen(ch));
111 else
112 strcpy(buf, "");
113 }
114 return buf;
115}
116
117/* send an SQL query to the database */
118int db_query(const char *fmt, ...)
119{
120 va_list args;
121 char buf[2048]; /* should be enough for long queries (don't underestimate :o)) */
122 va_start(args, fmt);
123 vsprintf(buf, fmt, args);
124 if (verbose)
125 log(">SQL : %s", buf);
126 if (mysql_real_query(myptr, buf, strlen(buf)))
127 fatal("Query failed: %s", mysql_error(myptr));
128 return 0;
129}
130
131/* serv should be db_escape'd before call */
132/* -1 if server not found, servid else */
133int db_checkserver(char *serv)
134{
135 int servid = -1;
136 MYSQL_RES *resptr;
137 db_query("SELECT servid FROM " TBL_SERV " WHERE server=\"%s\"", serv);
138 resptr = mysql_store_result(myptr);
139 if (mysql_num_rows(resptr))
140 servid = atoi(*mysql_fetch_row(resptr));
141 mysql_free_result(resptr);
142 return servid;
143}
144
145/* serv should be db_escape'd before call */
146int db_getserver(char *serv)
147{
148#ifdef HASHLISTSUPPORT
149 strtolwr(serv);
150 return hash_find(hashservs, serv, KEYOTHER);
151#else
152 MYSQL_RES *resptr;
153 int res = 0;
154
155 db_query("SELECT servid FROM " TBL_SERV " WHERE server=\'%s\'", serv);
156 resptr = mysql_store_result(myptr);
157 if (mysql_num_rows(resptr))
158 res = atoi(*mysql_fetch_row(resptr));
159 mysql_free_result(resptr);
160 return res;
161#endif
162}
163
164/* changes a nick in the hashlist */
165void db_chgnick(char *newnick, char *oldnick)
166{
167#ifdef HASHLISTSUPPORT
168 /* people often change from NICK-sthing to NICK-sthing */
169 strtolwr(newnick);
170 strtolwr(oldnick);
171 hash_update(hashnicks, newnick, oldnick, KEYOTHER);
172#endif
173}
174
175/* remove a server from the hashlist */
176void db_delserver(char *server)
177{
178#ifdef HASHLISTSUPPORT
179 strtolwr(server);
180 hash_del(hashservs, server, KEYOTHER);
181#endif
182}
183
184/* add a server to the hashlist */
185void db_addserver(char *server, int servid)
186{
187#ifdef HASHLISTSUPPORT
188 strtolwr(server);
189 hash_add(hashservs, server, servid, KEYOTHER);
190#endif
191}
192
193/* add a nick to the hashlist */
194void db_addnick(char *nick, int nickid)
195{
196#ifdef HASHLISTSUPPORT
197 strtolwr(nick);
198 hash_add(hashnicks, nick, nickid, KEYOTHER);
199#endif
200}
201
202/* add a nick to the hashlist */
203void db_delnick(char *nick)
204{
205#ifdef HASHLISTSUPPORT
206 strtolwr(nick);
207 hash_del(hashnicks, nick, KEYOTHER);
208#endif
209}
210
211/* nick should be db_escape'd before call */
212/* -1 if nick not found, nickid else */
213int db_checknick(char *nick)
214{
215#ifdef HASHLISTSUPPORT
216 int res = 0;
217 char *nicklow = strdup(nick);
218 strtolwr(nicklow);
219 res = hash_find_unsure(hashnicks, nicklow, KEYOTHER);
220 free(nicklow);
221 return res;
222#else
223 int nickid = -1;
224 MYSQL_RES *resptr;
225 db_query("SELECT nickid FROM " TBL_USER " WHERE nick=\"%s\"", nick);
226 resptr = mysql_store_result(myptr);
227 if (mysql_num_rows(resptr))
228 nickid = atoi(*mysql_fetch_row(resptr));
229 mysql_free_result(resptr);
230 return nickid;
231#endif
232}
233
234/* nick should be db_escape'd before call */
235int db_getnick(char *nick)
236{
237#ifdef HASHLISTSUPPORT
238 int res = 0;
239 char *nicklow = strdup(nick);
240 strtolwr(nicklow);
241 res = hash_find(hashnicks, nicklow, KEYOTHER);
242 free(nicklow);
243 return res;
244#else
245 MYSQL_RES *resptr;
246 int res = 0;
247
248 db_query("SELECT nickid FROM " TBL_USER " WHERE nick=\'%s\'", nick);
249 resptr = mysql_store_result(myptr);
250 if (mysql_num_rows(resptr))
251 res = atoi(*mysql_fetch_row(resptr));
252 else
253 fatal("nickname not found !");
254 mysql_free_result(resptr);
255 return res;
256#endif
257}
258
259int db_getservfromnick(char *nick)
260{
261 MYSQL_RES *resptr;
262 int res = 0;
263 db_query("SELECT servid FROM " TBL_USER " WHERE nick=\'%s\'", nick);
264 resptr = mysql_store_result(myptr);
265 if (mysql_num_rows(resptr))
266 res = atoi(*mysql_fetch_row(resptr));
267 else
268 fatal("nickname not found !");
269 mysql_free_result(resptr);
270 return res;
271}
272
273int db_insertid()
274{
275 return mysql_insert_id(myptr);
276}
277
278void db_removenick(char *nick)
279{
280 int nickid = db_getnick(nick);
281 //TODO
282 if (nickid == 0)
283 fatal("nickid 0");
284 db_removefromchans(nickid);
285 if (UserCacheTime)
286 db_query("UPDATE " TBL_USER
287 " SET online=\"N\", lastquit=NOW(), servid=NULL WHERE nickid=\"%d\"",
288 nickid);
289 else
290 db_query("DELETE FROM " TBL_USER " WHERE nickid=\'%d\'", nickid);
291}
292
293
294void db_removefromchans(int nickid)
295{
296 MYSQL_RES *resptr;
297 char **res;
298 db_query("SELECT " TBL_ISON ".chanid, channel FROM " TBL_ISON ", "
299 TBL_CHAN " WHERE nickid=\'%d\' AND " TBL_CHAN ".chanid = "
300 TBL_ISON ".chanid", nickid);
301 resptr = mysql_store_result(myptr);
302 db_query("DELETE FROM " TBL_ISON " WHERE nickid=\'%d\'", nickid);
303 while ((res = mysql_fetch_row(resptr)))
304 {
305 char *chan = db_escape(res[1]);
306 db_checkemptychan(atoi(res[0]), chan);
307 free(chan);
308 }
309 mysql_free_result(resptr);
310}
311
312void db_checkemptychan(int chanid, char *chan)
313{
314 MYSQL_RES *resptr2;
315 db_query("SELECT chanid FROM " TBL_ISON " WHERE chanid=\'%d\'", chanid);
316 resptr2 = mysql_store_result(myptr);
317 if (!mysql_num_rows(resptr2))
318 {
319 db_query("DELETE FROM " TBL_CHAN " WHERE chanid=\'%d\'", chanid);
320#ifdef HASHLISTSUPPORT
321 hash_del(hashchans, chan, KEYCHAN);
322#endif
323 nbchans--;
324 }
325 mysql_free_result(resptr2);
326}
327
328int db_getlusers(int type)
329{
330 MYSQL_RES *resptr;
331 int retcode;
332 switch (type)
333 {
334 case LUSERS_USERS:
335 db_query("SELECT COUNT(*) FROM " TBL_USER " WHERE mode_li=\'N\'");
336 break;
337 case LUSERS_USERSINV:
338 db_query("SELECT COUNT(*) FROM " TBL_USER " WHERE mode_li=\'Y\'");
339 break;
340 case LUSERS_OPERS:
341 db_query("SELECT COUNT(*) FROM " TBL_USER " WHERE mode_lo=\'Y\'");
342 break;
343 case LUSERS_CHAN:
344 db_query("SELECT COUNT(*) FROM " TBL_CHAN);
345 break;
346 case LUSERS_SERV:
347 db_query("SELECT COUNT(*) FROM " TBL_SERV);
348 break;
349 case LUSERS_USERSGLOB:
350 db_query("SELECT COUNT(*) FROM " TBL_USER);
351 break;
352 case LUSERS_USERSMAX:
353 db_query("SELECT val FROM " TBL_MAXV " WHERE type='users'");
354 break;
355 }
356 resptr = mysql_store_result(myptr);
357 if (mysql_num_rows(resptr))
358 retcode = atoi(*mysql_fetch_row(resptr));
359 else
360 retcode = -1;
361 mysql_free_result(resptr);
362 return retcode;
363}
364
365/* chan should be db_escape'd before call */
366int db_getchannel(char *chan)
367{
368#ifdef HASHLISTSUPPORT
369 strtolwr(chan);
370 return hash_find(hashchans, chan, KEYCHAN);
371#else
372 int res = 0;
373
374 MYSQL_RES *resptr;
375 strtolwr(chan);
376 db_query("SELECT chanid FROM " TBL_CHAN " WHERE channel=\'%s\'", chan);
377 resptr = mysql_store_result(myptr);
378 if (mysql_num_rows(resptr))
379 res = atoi(*mysql_fetch_row(resptr));
380 else
381 fatal("channel not found !");
382 mysql_free_result(resptr);
383 return res;
384#endif
385}
386
387/* chan should be db_escape'd before call */
388/* chan is created if not exists */
389int db_getchancreate(char *chan)
390{
391 int res = -1;
392
393#ifdef HASHLISTSUPPORT
394 strtolwr(chan);
395 res = hash_find_unsure(hashchans, chan, KEYCHAN);
396#else
397 MYSQL_RES *resptr;
398 strtolwr(chan);
399 db_query("SELECT chanid FROM " TBL_CHAN " WHERE channel=\'%s\'", chan);
400 resptr = mysql_store_result(myptr);
401 if (mysql_num_rows(resptr))
402 res = atoi(*mysql_fetch_row(resptr));
403 mysql_free_result(resptr);
404#endif
405 if (res == -1)
406
407 {
408 db_query("INSERT INTO " TBL_CHAN " (channel) VALUES (\'%s\')", chan);
409 res = db_insertid();
410#ifdef HASHLISTSUPPORT
411 hash_add(hashchans, chan, res, KEYCHAN);
412#endif
413 nbchans++;
414 do_checknbchansmax();
415 }
416 return res;
417}
418
419/* close connection to DBMS */
420void db_close()
421{
422 if (myptr)
423 mysql_close(myptr);
424 myptr = NULL;
425}
426
427/* cleanup the server table, removing old entries */
428void db_cleanserver()
429{
430 MYSQL_RES *resptr;
431 int curtime = time(NULL);
432 char **res;
433 if (ServerLastClean == -1)
434 ServerLastClean = curtime;
435 if (curtime > (ServerLastClean + ServerCleanFreq))
436 {
437 ServerLastClean = curtime;
438 db_query("SELECT server FROM " TBL_SERV
439 " WHERE online=\"N\" AND lastsplit<FROM_UNIXTIME(\"%d\")",
440 curtime - ServerCacheTime);
441 resptr = mysql_store_result(myptr);
442 if (mysql_num_rows(resptr))
443 {
444 while ((res = mysql_fetch_row(resptr)))
445 {
446 char *server = db_escape(res[0]);
447 db_delserver(server);
448 free(server);
449 }
450 mysql_free_result(resptr);
451 db_query("DELETE FROM " TBL_SERV
452 " WHERE online=\"N\" AND lastsplit<FROM_UNIXTIME(\"%d\")",
453 curtime - ServerCacheTime);
454 }
455 }
456}
457
458/* cleanup the user table, removing old entries */
459void db_cleanuser()
460{
461 MYSQL_RES *resptr;
462 int curtime = time(NULL);
463 char **res;
464 if (UserLastClean == -1)
465 UserLastClean = curtime;
466 if (curtime > (UserLastClean + UserCleanFreq))
467 {
468 UserLastClean = curtime;
469 db_query("SELECT nick FROM " TBL_USER
470 " WHERE online=\"N\" AND lastquit<FROM_UNIXTIME(\"%d\")",
471 curtime - UserCacheTime);
472
473 resptr = mysql_store_result(myptr);
474 if (mysql_num_rows(resptr))
475 {
476 while ((res = mysql_fetch_row(resptr)))
477 {
478 char *nick = db_escape(res[0]);
479 db_delnick(nick);
480 free(nick);
481 }
482 mysql_free_result(resptr);
483 db_query("DELETE FROM " TBL_USER
484 " WHERE online=\"N\" AND lastquit<FROM_UNIXTIME(\"%d\")",
485 curtime - UserCacheTime);
486 }
487 }
488}