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