]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/database/chanservdb.c
Merge.
[irc/quakenet/newserv.git] / chanserv / database / chanservdb.c
1 /*
2 * chanservdb.c:
3 * Handles the SQL stuff for the channel service.
4 */
5
6 #include "../chanserv.h"
7 #include "../../pqsql/pqsql.h"
8 #include "../../core/config.h"
9 #include "../../lib/sstring.h"
10 #include "../../parser/parser.h"
11 #include "../../core/events.h"
12 #include "../../core/nsmalloc.h"
13 #include "../../lib/strlfunc.h"
14
15 #include <string.h>
16 #include <libpq-fe.h>
17 #include <stdio.h>
18 #include <sys/poll.h>
19 #include <stdarg.h>
20
21 int chanservdb_ready;
22
23 typedef struct tabledesc {
24 sstring *tablename; /* Name of table */
25 PQQueryHandler init; /* Function to be called when transaction opens */
26 PQQueryHandler data; /* Function to be called to load data */
27 PQQueryHandler fini; /* Function to be called to clean up */
28 } tabledesc;
29
30 regchan **allchans;
31 maillock *maillocks;
32
33 int chanservext;
34 int chanservaext;
35
36 unsigned int lastchannelID;
37 unsigned int lastuserID;
38 unsigned int lastbanID;
39 unsigned int lastdomainID;
40 unsigned int lastmaillockID;
41
42 /* Local prototypes */
43 void csdb_handlestats(int hooknum, void *arg);
44 void loadmessages_part1(PGconn *, void *);
45 void loadmessages_part2(PGconn *, void *);
46 void loadcommandsummary_real(PGconn *, void *);
47
48 /* Generic loading functions */
49 void loadall(char *, PQQueryHandler, PQQueryHandler, PQQueryHandler);
50 void doloadall(PGconn *, void *);
51
52 /* User loading functions */
53 void loadsomeusers(PGconn *, void *);
54 void loadusersdone(PGconn *, void *);
55
56 /* Channel loading functions */
57 void loadsomechannels(PGconn *, void *);
58 void loadchannelsdone(PGconn *, void *);
59
60 /* Chanuser loading functions */
61 void loadchanusersinit(PGconn *, void *);
62 void loadsomechanusers(PGconn *, void *);
63 void loadchanusersdone(PGconn *, void *);
64
65 /* Chanban loading functions */
66 void loadsomechanbans(PGconn *, void *);
67 void loadchanbansdone(PGconn *, void *);
68
69 /* Mail Domain loading functions */
70 void loadsomemaildomains(PGconn *, void *);
71 void loadmaildomainsdone(PGconn *, void *);
72
73 /* Mail lock loading functions */
74 void loadsomemaillocks(PGconn *, void *);
75 void loadmaillocksdone(PGconn *, void *);
76
77 /* Free sstrings in the structures */
78 void csdb_freestuff();
79
80 static void setuptables() {
81 /* Set up the tables */
82 /* User table */
83 pqcreatequery("CREATE TABLE users ("
84 "ID INT NOT NULL,"
85 "username VARCHAR(16) NOT NULL,"
86 "created INT NOT NULL,"
87 "lastauth INT NOT NULL,"
88 "lastemailchng INT NOT NULL,"
89 "flags INT NOT NULL,"
90 "language INT NOT NULL,"
91 "suspendby INT NOT NULL,"
92 "suspendexp INT NOT NULL,"
93 "suspendtime INT NOT NULL,"
94 "lockuntil INT NOT NULL,"
95 "password VARCHAR(11) NOT NULL,"
96 "email VARCHAR(100),"
97 "lastemail VARCHAR(100),"
98 "lastuserhost VARCHAR(75),"
99 "suspendreason VARCHAR(250),"
100 "comment VARCHAR(250),"
101 "info VARCHAR(100),"
102 "PRIMARY KEY (ID))");
103
104 pqcreatequery("CREATE INDEX user_username_index ON users (username)");
105
106 /* Channel table */
107 pqcreatequery("CREATE TABLE channels ("
108 "ID INT NOT NULL,"
109 "name VARCHAR(250) NOT NULL,"
110 "flags INT NOT NULL,"
111 "forcemodes INT NOT NULL,"
112 "denymodes INT NOT NULL,"
113 "chanlimit INT NOT NULL,"
114 "autolimit INT NOT NULL,"
115 "banstyle INT NOT NULL,"
116 "created INT NOT NULL,"
117 "lastactive INT NOT NULL,"
118 "statsreset INT NOT NULL,"
119 "banduration INT NOT NULL,"
120 "founder INT NOT NULL,"
121 "addedby INT NOT NULL,"
122 "suspendby INT NOT NULL,"
123 "suspendtime INT NOT NULL,"
124 "chantype SMALLINT NOT NULL,"
125 "totaljoins INT NOT NULL,"
126 "tripjoins INT NOT NULL,"
127 "maxusers INT NOT NULL,"
128 "tripusers INT NOT NULL,"
129 "welcome VARCHAR(500),"
130 "topic VARCHAR(250),"
131 "chankey VARCHAR(23),"
132 "suspendreason VARCHAR(250),"
133 "comment VARCHAR(250),"
134 "lasttimestamp INT,"
135 "PRIMARY KEY (ID))");
136
137 /* Chanuser table */
138 pqcreatequery("CREATE TABLE chanusers ("
139 "userID INT NOT NULL,"
140 "channelID INT NOT NULL,"
141 "flags INT NOT NULL,"
142 "changetime INT NOT NULL,"
143 "usetime INT NOT NULL,"
144 "info VARCHAR(100) NOT NULL,"
145 "PRIMARY KEY (userID, channelID))");
146
147 pqcreatequery("CREATE INDEX chanusers_userID_index on chanusers (userID)");
148 pqcreatequery("CREATE INDEX chanusers_channelID_index on chanusers (channelID)");
149
150 pqcreatequery("CREATE TABLE bans ("
151 "banID INT NOT NULL," /* Unique number for the ban to make
152 DELETEs process in finite time.. */
153 "channelID INT NOT NULL,"
154 "userID INT NOT NULL," /* Who set the ban.. */
155 "hostmask VARCHAR(100) NOT NULL," /* needs to be at least USERLEN+NICKLEN+HOSTLEN+2 */
156 "expiry INT NOT NULL,"
157 "reason VARCHAR(200),"
158 "PRIMARY KEY(banID))");
159
160 pqcreatequery("CREATE INDEX bans_channelID_index on bans (channelID)");
161
162 pqcreatequery("CREATE TABLE languages ("
163 "languageID INT NOT NULL,"
164 "code VARCHAR(2) NOT NULL,"
165 "name VARCHAR(30) NOT NULL)");
166
167 pqcreatequery("CREATE TABLE messages ("
168 "languageID INT NOT NULL,"
169 "messageID INT NOT NULL,"
170 "message VARCHAR(250) NOT NULL,"
171 "PRIMARY KEY (languageID, messageID))");
172
173 pqcreatequery("CREATE TABLE help ("
174 "commandID INT NOT NULL,"
175 "command VARCHAR(30) NOT NULL,"
176 "languageID INT NOT NULL,"
177 "summary VARCHAR(200) NOT NULL,"
178 "fullinfo TEXT NOT NULL,"
179 "PRIMARY KEY (commandID, languageID))");
180
181 pqcreatequery("CREATE TABLE email ("
182 "userID INT NOT NULL,"
183 "emailtype INT NOT NULL,"
184 "prevEmail VARCHAR(100),"
185 "mailID SERIAL,"
186 "PRIMARY KEY (mailID))");
187
188 pqcreatequery("CREATE TABLE maildomain ("
189 "ID INT NOT NULL,"
190 "name VARCHAR NOT NULL,"
191 "domainlimit INT NOT NULL,"
192 "actlimit INT NOT NULL,"
193 "flags INT NOT NULL,"
194 "PRIMARY KEY (ID))");
195
196 pqcreatequery("CREATE TABLE authhistory ("
197 "userID INT NOT NULL,"
198 "nick VARCHAR(15) NOT NULL,"
199 "username VARCHAR(10) NOT NULL,"
200 "host VARCHAR(63) NOT NULL,"
201 "authtime INT NOT NULL,"
202 "disconnecttime INT NOT NULL,"
203 "numeric INT NOT NULL,"
204 "quitreason VARCHAR(100) ,"
205 "PRIMARY KEY (userID, authtime))");
206
207 pqcreatequery("CREATE INDEX authhistory_userID_index on authhistory(userID)");
208 pqcreatequery("CREATE TABLE chanlevhistory ("
209 "userID INT NOT NULL,"
210 "channelID INT NOT NULL,"
211 "targetID INT NOT NULL,"
212 "changetime INT NOT NULL,"
213 "authtime INT NOT NULL,"
214 "oldflags INT NOT NULL,"
215 "newflags INT NOT NULL)");
216
217 pqcreatequery("CREATE INDEX chanlevhistory_userID_index on chanlevhistory(userID)");
218 pqcreatequery("CREATE INDEX chanlevhistory_channelID_index on chanlevhistory(channelID)");
219 pqcreatequery("CREATE INDEX chanlevhistory_targetID_index on chanlevhistory(targetID)");
220
221 pqcreatequery("CREATE TABLE accounthistory ("
222 "userID INT NOT NULL,"
223 "changetime INT NOT NULL,"
224 "authtime INT NOT NULL,"
225 "oldpassword VARCHAR(11),"
226 "newpassword VARCHAR(11),"
227 "oldemail VARCHAR(100),"
228 "newemail VARCHAR(100),"
229 "PRIMARY KEY (userID, changetime))");
230
231 pqcreatequery("CREATE INDEX accounthistory_userID_index on accounthistory(userID)");
232
233 pqcreatequery("CREATE TABLE maillocks ("
234 "ID INT NOT NULL,"
235 "pattern VARCHAR NOT NULL,"
236 "reason VARCHAR NOT NULL,"
237 "createdby INT NOT NULL,"
238 "created INT NOT NULL,"
239 "PRIMARY KEY (ID))");
240 }
241
242 void _init() {
243 chanservext=registerchanext("chanserv");
244 chanservaext=registerauthnameext("chanserv");
245
246 /* Set up the allocators and hashes */
247 chanservallocinit();
248 chanservhashinit();
249
250 /* And the messages */
251 initmessages();
252
253 if (pqconnected() && (chanservext!=-1) && (chanservaext!=-1)) {
254 registerhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
255
256 setuptables();
257
258 lastuserID=lastchannelID=lastdomainID=0;
259
260 loadall("users",NULL,loadsomeusers,loadusersdone);
261 loadall("channels",NULL,loadsomechannels,loadchannelsdone);
262 loadall("chanusers",loadchanusersinit,loadsomechanusers,loadchanusersdone);
263 loadall("bans",NULL,loadsomechanbans,loadchanbansdone);
264 loadall("maildomain",NULL, loadsomemaildomains,loadmaildomainsdone);
265 loadall("maillocks",NULL, loadsomemaillocks,loadmaillocksdone);
266
267 loadmessages();
268 }
269 }
270
271 void _fini() {
272 deregisterhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
273
274 csdb_freestuff();
275
276 if (chanservext!=-1)
277 releasechanext(chanservext);
278
279 if (chanservaext!=-1)
280 releaseauthnameext(chanservaext);
281
282 nsfreeall(POOL_CHANSERVDB);
283 }
284
285 void csdb_handlestats(int hooknum, void *arg) {
286 /* long level=(long)arg; */
287
288 /* Keeping options open here */
289 }
290
291 void chanservdbclose() {
292
293 deregisterhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
294
295 }
296
297 /*
298 * loadall():
299 * Generic function to handle load of an entire table..
300 */
301
302 void loadall(char *table, PQQueryHandler init, PQQueryHandler data, PQQueryHandler fini) {
303 tabledesc *thedesc;
304
305 thedesc=malloc(sizeof(tabledesc));
306
307 thedesc->tablename=getsstring(table,100);
308 thedesc->init=init;
309 thedesc->data=data;
310 thedesc->fini=fini;
311
312 pqasyncquery(doloadall, thedesc, "SELECT count(*) FROM %s",thedesc->tablename->content);
313 }
314
315 void doloadall(PGconn *dbconn, void *arg) {
316 PGresult *pgres;
317 int i,count;
318 tabledesc *thedesc=arg;
319
320 pgres=PQgetResult(dbconn);
321
322 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
323 Error("chanserv",ERR_ERROR,"Error getting row count for %s.",thedesc->tablename->content);
324 return;
325 }
326
327 if (PQnfields(pgres)!=1) {
328 Error("chanserv",ERR_ERROR,"Count query format error for %s.",thedesc->tablename->content);
329 return;
330 }
331
332 count=strtoul(PQgetvalue(pgres,0,0),NULL,10);
333
334 PQclear(pgres);
335
336 Error("chanserv",ERR_INFO,"Found %d entries in table %s, scheduling load.",count,
337 thedesc->tablename->content);
338
339 pqasyncquery(thedesc->init, NULL, "BEGIN");
340 pqquery("DECLARE mycurs CURSOR FOR SELECT * from %s",
341 thedesc->tablename->content);
342
343 for (i=0;(count-i)>1000;i+=1000) {
344 pqasyncquery(thedesc->data, NULL, "FETCH 1000 FROM mycurs");
345 }
346
347 pqasyncquery(thedesc->data, NULL, "FETCH ALL FROM mycurs");
348
349 pqquery("CLOSE mycurs");
350 pqasyncquery(thedesc->fini, NULL, "COMMIT");
351
352 /* Free structures.. */
353 freesstring(thedesc->tablename);
354 free(thedesc);
355 }
356
357 /*
358 * loadsomeusers():
359 * Loads some users in from the SQL DB
360 */
361
362 void loadsomeusers(PGconn *dbconn, void *arg) {
363 PGresult *pgres;
364 reguser *rup;
365 unsigned int i,num;
366 char *local;
367 char mailbuf[1024];
368
369 pgres=PQgetResult(dbconn);
370
371 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
372 Error("chanserv",ERR_ERROR,"Error loading user DB");
373 return;
374 }
375
376 if (PQnfields(pgres)!=18) {
377 Error("chanserv",ERR_ERROR,"User DB format error");
378 return;
379 }
380
381 num=PQntuples(pgres);
382
383 for(i=0;i<num;i++) {
384 rup=getreguser();
385 rup->status=0;
386 rup->ID=strtoul(PQgetvalue(pgres,i,0),NULL,10);
387 strncpy(rup->username,PQgetvalue(pgres,i,1),NICKLEN); rup->username[NICKLEN]='\0';
388 rup->created=strtoul(PQgetvalue(pgres,i,2),NULL,10);
389 rup->lastauth=strtoul(PQgetvalue(pgres,i,3),NULL,10);
390 rup->lastemailchange=strtoul(PQgetvalue(pgres,i,4),NULL,10);
391 rup->flags=strtoul(PQgetvalue(pgres,i,5),NULL,10);
392 rup->languageid=strtoul(PQgetvalue(pgres,i,6),NULL,10);
393 rup->suspendby=strtoul(PQgetvalue(pgres,i,7),NULL,10);
394 rup->suspendexp=strtoul(PQgetvalue(pgres,i,8),NULL,10);
395 rup->suspendtime=strtoul(PQgetvalue(pgres,i,9),NULL,10);
396 rup->lockuntil=strtoul(PQgetvalue(pgres,i,10),NULL,10);
397 strncpy(rup->password,PQgetvalue(pgres,i,11),PASSLEN); rup->password[PASSLEN]='\0';
398 rup->email=getsstring(PQgetvalue(pgres,i,12),100);
399 if (rup->email) {
400 rup->domain=findorcreatemaildomain(rup->email->content);
401 addregusertomaildomain(rup, rup->domain);
402
403 strlcpy(mailbuf, rup->email->content, sizeof(mailbuf));
404 if((local=strchr(mailbuf, '@'))) {
405 *(local++)='\0';
406 rup->localpart=getsstring(mailbuf,EMAILLEN);
407 } else {
408 rup->localpart=NULL;
409 }
410 } else {
411 rup->domain=NULL;
412 rup->localpart=NULL;
413 }
414 rup->lastemail=getsstring(PQgetvalue(pgres,i,13),100);
415 rup->lastuserhost=getsstring(PQgetvalue(pgres,i,14),75);
416 rup->suspendreason=getsstring(PQgetvalue(pgres,i,15),250);
417 rup->comment=getsstring(PQgetvalue(pgres,i,16),250);
418 rup->info=getsstring(PQgetvalue(pgres,i,17),100);
419 rup->knownon=NULL;
420 rup->checkshd=NULL;
421 rup->stealcount=0;
422 rup->fakeuser=NULL;
423 addregusertohash(rup);
424
425 if (rup->ID > lastuserID) {
426 lastuserID=rup->ID;
427 }
428 }
429
430 PQclear(pgres);
431 }
432
433 void loadusersdone(PGconn *conn, void *arg) {
434 Error("chanserv",ERR_INFO,"Load users done (highest ID was %d)",lastuserID);
435 }
436
437 /*
438 * Channel loading functions
439 */
440
441 void loadsomechannels(PGconn *dbconn, void *arg) {
442 PGresult *pgres;
443 regchan *rcp;
444 int i,j,num;
445 chanindex *cip;
446 time_t now=time(NULL);
447
448 pgres=PQgetResult(dbconn);
449
450 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
451 Error("chanserv",ERR_ERROR,"Error loading channel DB");
452 return;
453 }
454
455 if (PQnfields(pgres)!=27) {
456 Error("chanserv",ERR_ERROR,"Channel DB format error");
457 return;
458 }
459
460 num=PQntuples(pgres);
461
462 for(i=0;i<num;i++) {
463 cip=findorcreatechanindex(PQgetvalue(pgres,i,1));
464 if (cip->exts[chanservext]) {
465 Error("chanserv",ERR_WARNING,"%s in database twice - this WILL cause problems later.",cip->name->content);
466 continue;
467 }
468 rcp=getregchan();
469 cip->exts[chanservext]=rcp;
470
471 rcp->ID=strtoul(PQgetvalue(pgres,i,0),NULL,10);
472 rcp->index=cip;
473 rcp->flags=strtoul(PQgetvalue(pgres,i,2),NULL,10);
474 rcp->status=0; /* Non-DB field */
475 rcp->lastbancheck=0;
476 rcp->lastcountersync=now;
477 rcp->lastpart=0;
478 rcp->bans=NULL;
479 rcp->forcemodes=strtoul(PQgetvalue(pgres,i,3),NULL,10);
480 rcp->denymodes=strtoul(PQgetvalue(pgres,i,4),NULL,10);
481 rcp->limit=strtoul(PQgetvalue(pgres,i,5),NULL,10);
482 rcp->autolimit=strtoul(PQgetvalue(pgres,i,6),NULL,10);
483 rcp->banstyle=strtoul(PQgetvalue(pgres,i,7),NULL,10);
484 rcp->created=strtoul(PQgetvalue(pgres,i,8),NULL,10);
485 rcp->lastactive=strtoul(PQgetvalue(pgres,i,9),NULL,10);
486 rcp->statsreset=strtoul(PQgetvalue(pgres,i,10),NULL,10);
487 rcp->banduration=strtoul(PQgetvalue(pgres,i,11),NULL,10);
488 rcp->founder=strtol(PQgetvalue(pgres,i,12),NULL,10);
489 rcp->addedby=strtol(PQgetvalue(pgres,i,13),NULL,10);
490 rcp->suspendby=strtol(PQgetvalue(pgres,i,14),NULL,10);
491 rcp->suspendtime=strtol(PQgetvalue(pgres,i,15),NULL,10);
492 rcp->chantype=strtoul(PQgetvalue(pgres,i,16),NULL,10);
493 rcp->totaljoins=strtoul(PQgetvalue(pgres,i,17),NULL,10);
494 rcp->tripjoins=strtoul(PQgetvalue(pgres,i,18),NULL,10);
495 rcp->maxusers=strtoul(PQgetvalue(pgres,i,19),NULL,10);
496 rcp->tripusers=strtoul(PQgetvalue(pgres,i,20),NULL,10);
497 rcp->welcome=getsstring(PQgetvalue(pgres,i,21),500);
498 rcp->topic=getsstring(PQgetvalue(pgres,i,22),TOPICLEN);
499 rcp->key=getsstring(PQgetvalue(pgres,i,23),KEYLEN);
500 rcp->suspendreason=getsstring(PQgetvalue(pgres,i,24),250);
501 rcp->comment=getsstring(PQgetvalue(pgres,i,25),250);
502 rcp->checksched=NULL;
503 rcp->ltimestamp=strtoul(PQgetvalue(pgres,i,26),NULL,10);
504 memset(rcp->regusers,0,REGCHANUSERHASHSIZE*sizeof(reguser *));
505
506 if (rcp->ID > lastchannelID)
507 lastchannelID=rcp->ID;
508
509 if (CIsAutoLimit(rcp))
510 rcp->limit=0;
511
512 for (j=0;j<CHANOPHISTORY;j++) {
513 rcp->chanopnicks[j][0]='\0';
514 rcp->chanopaccts[j]=0;
515 }
516 rcp->chanoppos=0;
517 }
518
519 PQclear(pgres);
520 }
521
522 void loadchannelsdone(PGconn *dbconn, void *arg) {
523 Error("chanserv",ERR_INFO,"Channel load done (highest ID was %d)",lastchannelID);
524 }
525
526 void loadchanusersinit(PGconn *dbconn, void *arg) {
527 int i;
528 chanindex *cip;
529 regchan *rcp;
530
531 allchans=(regchan **)malloc((lastchannelID+1)*sizeof(regchan *));
532 memset(allchans,0,(lastchannelID+1)*sizeof(regchan *));
533 for (i=0;i<CHANNELHASHSIZE;i++) {
534 for (cip=chantable[i];cip;cip=cip->next) {
535 if (cip->exts[chanservext]) {
536 rcp=(regchan *)cip->exts[chanservext];
537 allchans[rcp->ID]=rcp;
538 }
539 }
540 }
541 }
542
543 void loadsomechanusers(PGconn *dbconn, void *arg) {
544 PGresult *pgres;
545 regchanuser *rcup;
546 int i,num;
547 regchan *rcp;
548 reguser *rup;
549 authname *anp;
550 int uid,cid;
551 int total=0;
552
553 /* Set up the allchans array */
554 pgres=PQgetResult(dbconn);
555
556 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
557 Error("chanserv",ERR_ERROR,"Error loading chanusers.");
558 return;
559 }
560
561 if (PQnfields(pgres)!=6) {
562 Error("chanserv",ERR_ERROR,"Chanusers format error");
563 return;
564 }
565
566 num=PQntuples(pgres);
567
568 for(i=0;i<num;i++) {
569 uid=strtol(PQgetvalue(pgres,i,0),NULL,10);
570 cid=strtol(PQgetvalue(pgres,i,1),NULL,10);
571
572 if (!(anp=findauthname(uid)) || !(rup=anp->exts[chanservaext])) {
573 Error("chanserv",ERR_WARNING,"Skipping channeluser for unknown user %d",uid);
574 continue;
575 }
576
577 if (cid>lastchannelID || !(rcp=allchans[cid])) {
578 Error("chanserv",ERR_WARNING,"Skipping channeluser for unknown chan %d",cid);
579 continue;
580 }
581
582 if (rup==NULL || rcp==NULL) {
583 Error("chanserv",ERR_ERROR,"Can't add user %s on channel %s",
584 PQgetvalue(pgres,i,0),PQgetvalue(pgres,i,1));
585 } else {
586 rcup=getregchanuser();
587 rcup->user=rup;
588 rcup->chan=rcp;
589 rcup->flags=strtol(PQgetvalue(pgres,i,2),NULL,10);
590 rcup->changetime=strtol(PQgetvalue(pgres,i,3),NULL,10);
591 rcup->usetime=strtol(PQgetvalue(pgres,i,4),NULL,10);
592 rcup->info=getsstring(PQgetvalue(pgres,i,5),100);
593 addregusertochannel(rcup);
594 total++;
595 }
596 }
597
598 PQclear(pgres);
599 }
600
601 void loadchanusersdone(PGconn *dbconn, void *arg) {
602 Error("chanserv",ERR_INFO,"Channel user load done.");
603 }
604
605 void loadsomechanbans(PGconn *dbconn, void *arg) {
606 PGresult *pgres;
607 regban *rbp;
608 int i,num;
609 regchan *rcp;
610 int uid,cid,bid;
611 time_t expiry,now;
612 int total=0;
613
614 pgres=PQgetResult(dbconn);
615
616 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
617 Error("chanserv",ERR_ERROR,"Error loading bans.");
618 return;
619 }
620
621 if (PQnfields(pgres)!=6) {
622 Error("chanserv",ERR_ERROR,"Ban format error");
623 return;
624 }
625
626 num=PQntuples(pgres);
627
628 now=time(NULL);
629
630 for(i=0;i<num;i++) {
631 bid=strtoul(PQgetvalue(pgres,i,0),NULL,10);
632 cid=strtoul(PQgetvalue(pgres,i,1),NULL,10);
633 uid=strtoul(PQgetvalue(pgres,i,2),NULL,10);
634 expiry=strtoul(PQgetvalue(pgres,i,4),NULL,10);
635
636 if (cid>lastchannelID || !(rcp=allchans[cid])) {
637 Error("chanserv",ERR_WARNING,"Skipping ban for unknown chan %d",cid);
638 continue;
639 }
640
641 rbp=getregban();
642 rbp->setby=uid;
643 rbp->ID=bid;
644 rbp->expiry=expiry;
645 rbp->reason=getsstring(PQgetvalue(pgres,i,5),200);
646 rbp->cbp=makeban(PQgetvalue(pgres,i,3));
647 rbp->next=rcp->bans;
648 rcp->bans=rbp;
649
650 total++;
651
652 if (bid>lastbanID)
653 lastbanID=bid;
654 }
655
656 PQclear(pgres);
657 }
658
659 void loadchanbansdone(PGconn *dbconn, void *arg) {
660 free(allchans);
661
662 Error("chanserv",ERR_INFO,"Channel ban load done, highest ID was %d",lastbanID);
663
664 chanservdb_ready=1;
665 triggerhook(HOOK_CHANSERV_DBLOADED, NULL);
666 }
667
668 void loadmessages() {
669 pqasyncquery(loadmessages_part1, NULL, "SELECT * from languages");
670 }
671
672 void loadmessages_part1(PGconn *dbconn, void *arg) {
673 int i,j;
674 PGresult *pgres;
675 int num;
676
677 /* Firstly, clear up any stale messages */
678 for (i=0;i<MAXLANG;i++) {
679 if (cslanguages[i]) {
680 freesstring(cslanguages[i]->name);
681 free(cslanguages[i]);
682 }
683 for (j=0;j<MAXMESSAGES;j++) {
684 if (csmessages[i][j]) {
685 freesstring(csmessages[i][j]);
686 csmessages[i][j]=NULL;
687 }
688 }
689 }
690
691 pgres=PQgetResult(dbconn);
692
693 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
694 Error("chanserv",ERR_ERROR,"Error loading language list.");
695 return;
696 }
697
698 if (PQnfields(pgres)!=3) {
699 Error("chanserv",ERR_ERROR,"Language list format error.");
700 return;
701 }
702
703 num=PQntuples(pgres);
704
705 for (i=0;i<num;i++) {
706 j=strtol(PQgetvalue(pgres,i,0),NULL,10);
707 if (j<MAXLANG && j>=0) {
708 cslanguages[j]=(cslang *)malloc(sizeof(cslang));
709
710 strncpy(cslanguages[j]->code,PQgetvalue(pgres,i,1),2); cslanguages[j]->code[2]='\0';
711 cslanguages[j]->name=getsstring(PQgetvalue(pgres,i,2),30);
712 }
713 }
714
715 PQclear(pgres);
716
717 if (i>MAXLANG)
718 Error("chanserv",ERR_ERROR,"Found too many languages (%d > %d)",i,MAXLANG);
719
720 pqasyncquery(loadmessages_part2, NULL, "SELECT * from messages");
721 }
722
723 void loadmessages_part2(PGconn *dbconn, void *arg) {
724 PGresult *pgres;
725 int i,j,k,num;
726
727 pgres=PQgetResult(dbconn);
728
729 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
730 Error("chanserv",ERR_ERROR,"Error loading message list.");
731 return;
732 }
733
734 if (PQnfields(pgres)!=3) {
735 Error("chanserv",ERR_ERROR,"Message list format error.");
736 return;
737 }
738
739 num=PQntuples(pgres);
740
741 for (i=0;i<num;i++) {
742 k=strtol(PQgetvalue(pgres,i,0),NULL,10);
743 j=strtol(PQgetvalue(pgres,i,1),NULL,10);
744
745 if (k<0 || k >= MAXLANG) {
746 Error("chanserv",ERR_WARNING,"Language ID out of range on message: %d",k);
747 continue;
748 }
749
750 if (j<0 || j >= MAXMESSAGES) {
751 Error("chanserv",ERR_WARNING,"Message ID out of range on message: %d",j);
752 continue;
753 }
754
755 csmessages[k][j]=getsstring(PQgetvalue(pgres,i,2),250);
756 }
757
758 PQclear(pgres);
759 }
760
761 void loadcommandsummary(Command *cmd) {
762 pqasyncquery(loadcommandsummary_real, (void *)cmd,
763 "SELECT languageID,summary from help where lower(command) = lower('%s')",cmd->command->content);
764 }
765
766 void loadcommandsummary_real(PGconn *dbconn, void *arg) {
767 int i,j,num;
768 PGresult *pgres;
769 cmdsummary *cs;
770 Command *cmd=arg;
771
772 /* Clear up old text first */
773 cs=cmd->ext;
774 for (i=0;i<MAXLANG;i++) {
775 if (cs->bylang[i])
776 freesstring(cs->bylang[i]);
777 }
778
779 pgres=PQgetResult(dbconn);
780
781 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
782 Error("chanserv",ERR_ERROR,"Error loading command summary.");
783 return;
784 }
785
786 if (PQnfields(pgres)!=2) {
787 Error("chanserv",ERR_ERROR,"Command summary format error.");
788 PQclear(pgres);
789 return;
790 }
791
792 num=PQntuples(pgres);
793
794 for (i=0;i<num;i++) {
795 j=strtol(PQgetvalue(pgres,i,0),NULL,10);
796 if (j<MAXLANG && j>=0) {
797 cs->bylang[j]=getsstring(PQgetvalue(pgres,i,1),200);
798 }
799 }
800
801 PQclear(pgres);
802 }
803
804 void csdb_freestuff() {
805 int i;
806 chanindex *cip, *ncip;
807 regchan *rcp;
808 reguser *rup;
809 regchanuser *rcup;
810 regban *rbp;
811 maildomain *mdp;
812 maillock *mlp, *nmlp;
813
814 for (i=0;i<REGUSERHASHSIZE;i++) {
815 for (rup=regusernicktable[i];rup;rup=rup->nextbyname) {
816 freesstring(rup->email);
817 freesstring(rup->localpart);
818 freesstring(rup->lastemail);
819 freesstring(rup->lastuserhost);
820 freesstring(rup->suspendreason);
821 freesstring(rup->comment);
822 freesstring(rup->info);
823
824 for (rcup=rup->knownon;rcup;rcup=rcup->nextbyuser)
825 freesstring(rcup->info);
826 }
827 }
828
829 for (i=0;i<CHANNELHASHSIZE;i++) {
830 for (cip=chantable[i];cip;cip=ncip) {
831 ncip=cip->next;
832 if ((rcp=cip->exts[chanservext])) {
833 freesstring(rcp->welcome);
834 freesstring(rcp->topic);
835 freesstring(rcp->key);
836 freesstring(rcp->suspendreason);
837 freesstring(rcp->comment);
838 for (rbp=rcp->bans;rbp;rbp=rbp->next) {
839 freesstring(rbp->reason);
840 freechanban(rbp->cbp);
841 }
842 cip->exts[chanservext]=NULL;
843 releasechanindex(cip);
844 }
845 }
846 }
847
848 for (i=0; i<MAILDOMAINHASHSIZE; i++) {
849 for (mdp=maildomainnametable[i]; mdp; mdp=mdp->nextbyname)
850 freesstring(mdp->name);
851 }
852
853 for(mlp=maillocks;mlp;mlp=nmlp) {
854 nmlp=mlp->next;
855 freemaillock(mlp);
856 }
857 maillocks=NULL;
858 }
859
860 void loadsomemaildomains(PGconn *dbconn,void *arg) {
861 PGresult *pgres;
862 maildomain *mdp;
863 unsigned int i,num;
864 char *domain;
865 pgres=PQgetResult(dbconn);
866
867 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
868 Error("chanserv",ERR_ERROR,"Error loading maildomain DB");
869 return;
870 }
871
872 if (PQnfields(pgres)!=5) {
873 Error("chanserv",ERR_ERROR,"Mail Domain DB format error");
874 return;
875 }
876 num=PQntuples(pgres);
877 lastdomainID=0;
878
879 for(i=0;i<num;i++) {
880 domain=PQgetvalue(pgres,i,1);
881 mdp=findorcreatemaildomain(domain); //@@@ LEN
882
883 mdp->ID=strtoul(PQgetvalue(pgres,i,0),NULL,10);
884 mdp->limit=strtoul(PQgetvalue(pgres,i,2),NULL,10);
885 mdp->actlimit=strtoul(PQgetvalue(pgres,i,3),NULL,10);
886 mdp->flags=strtoul(PQgetvalue(pgres,i,4),NULL,10);
887
888 if (mdp->ID > lastdomainID) {
889 lastdomainID=mdp->ID;
890 }
891 }
892
893 PQclear(pgres);
894 }
895
896 void loadmaildomainsdone(PGconn *dbconn, void *arg) {
897 Error("chanserv",ERR_INFO,"Load Mail Domains done (highest ID was %d)",lastdomainID);
898 }
899
900 void loadsomemaillocks(PGconn *dbconn,void *arg) {
901 PGresult *pgres;
902 maillock *mlp;
903 unsigned int i,num;
904 pgres=PQgetResult(dbconn);
905
906 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
907 Error("chanserv",ERR_ERROR,"Error loading maillock DB");
908 return;
909 }
910
911 if (PQnfields(pgres)!=5) {
912 Error("chanserv",ERR_ERROR,"Maillock DB format error");
913 return;
914 }
915 num=PQntuples(pgres);
916 lastmaillockID=0;
917
918 for(i=0;i<num;i++) {
919 mlp=getmaillock();
920 mlp->id=strtoul(PQgetvalue(pgres,i,0),NULL,10);
921 mlp->pattern=getsstring(PQgetvalue(pgres,i,1), 300);
922 mlp->reason=getsstring(PQgetvalue(pgres,i,2), 300);
923 mlp->createdby=strtoul(PQgetvalue(pgres,i,3),NULL,10);
924 mlp->created=strtoul(PQgetvalue(pgres,i,4),NULL,10);
925 mlp->next=maillocks;
926 maillocks=mlp;
927
928 if (mlp->id > lastmaillockID)
929 lastmaillockID=mlp->id;
930 }
931
932 PQclear(pgres);
933 }
934
935 void loadmaillocksdone(PGconn *dbconn, void *arg) {
936 Error("chanserv",ERR_INFO,"Load Mail Locks done (highest ID was %d)",lastmaillockID);
937 }
938