]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/database/chanservdb.c
Merge pull request #132 from retropc/lua_country
[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 hashes */
240 chanservhashinit();
241
242 /* And the messages */
243 initmessages();
244
245 if (dbconnected() && (chanservext!=-1) && (chanservaext!=-1)) {
246 registerhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
247
248 setuptables();
249
250 lastuserID=lastchannelID=lastdomainID=0;
251
252 dbloadtable("chanserv.users",NULL,loadsomeusers,loadusersdone);
253 dbloadtable("chanserv.channels",NULL,loadsomechannels,loadchannelsdone);
254 dbloadtable("chanserv.chanusers",loadchanusersinit,loadsomechanusers,loadchanusersdone);
255 dbloadtable("chanserv.bans",NULL,loadsomechanbans,loadchanbansdone);
256 dbloadtable("chanserv.maildomain",NULL, loadsomemaildomains,loadmaildomainsdone);
257 dbloadtable("chanserv.maillocks",NULL, loadsomemaillocks,loadmaillocksdone);
258
259 loadmessages();
260 }
261 }
262
263 void _fini() {
264 deregisterhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
265
266 csdb_freestuff();
267
268 if (chanservext!=-1)
269 releasechanext(chanservext);
270
271 if (chanservaext!=-1)
272 releaseauthnameext(chanservaext);
273
274 nsfreeall(POOL_CHANSERVDB);
275 dbdetach("chanserv");
276 }
277
278 void csdb_handlestats(int hooknum, void *arg) {
279 /* long level=(long)arg; */
280
281 /* Keeping options open here */
282 }
283
284 void chanservdbclose() {
285
286 deregisterhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
287
288 }
289
290 /*
291 * loadsomeusers():
292 * Loads some users in from the SQL DB
293 */
294
295 void loadsomeusers(DBConn *dbconn, void *arg) {
296 DBResult *pgres;
297 reguser *rup;
298 char *local;
299 char mailbuf[1024];
300
301 pgres=dbgetresult(dbconn);
302
303 if (!dbquerysuccessful(pgres)) {
304 Error("chanserv",ERR_ERROR,"Error loading user DB");
305 return;
306 }
307
308 if (dbnumfields(pgres)!=19) {
309 Error("chanserv",ERR_ERROR,"User DB format error");
310 return;
311 }
312
313 while(dbfetchrow(pgres)) {
314 rup=getreguser();
315 rup->status=0;
316 rup->ID=strtoul(dbgetvalue(pgres,0),NULL,10);
317 strncpy(rup->username,dbgetvalue(pgres,1),NICKLEN); rup->username[NICKLEN]='\0';
318 rup->created=strtoul(dbgetvalue(pgres,2),NULL,10);
319 rup->lastauth=strtoul(dbgetvalue(pgres,3),NULL,10);
320 rup->lastemailchange=strtoul(dbgetvalue(pgres,4),NULL,10);
321 rup->flags=strtoul(dbgetvalue(pgres,5),NULL,10);
322 rup->languageid=strtoul(dbgetvalue(pgres,6),NULL,10);
323 rup->suspendby=strtoul(dbgetvalue(pgres,7),NULL,10);
324 rup->suspendexp=strtoul(dbgetvalue(pgres,8),NULL,10);
325 rup->suspendtime=strtoul(dbgetvalue(pgres,9),NULL,10);
326 rup->lockuntil=strtoul(dbgetvalue(pgres,10),NULL,10);
327 strncpy(rup->password,dbgetvalue(pgres,11),PASSLEN); rup->password[PASSLEN]='\0';
328 rup->email=getsstring(dbgetvalue(pgres,12),100);
329 if (rup->email) {
330 rup->domain=findorcreatemaildomain(rup->email->content);
331 addregusertomaildomain(rup, rup->domain);
332
333 strlcpy(mailbuf, rup->email->content, sizeof(mailbuf));
334 if((local=strchr(mailbuf, '@'))) {
335 *(local++)='\0';
336 rup->localpart=getsstring(mailbuf,EMAILLEN);
337 } else {
338 rup->localpart=NULL;
339 }
340 } else {
341 rup->domain=NULL;
342 rup->localpart=NULL;
343 }
344 rup->lastemail=getsstring(dbgetvalue(pgres,13),100);
345 rup->lastuserhost=getsstring(dbgetvalue(pgres,14),75);
346 rup->suspendreason=getsstring(dbgetvalue(pgres,15),250);
347 rup->comment=getsstring(dbgetvalue(pgres,16),250);
348 rup->info=getsstring(dbgetvalue(pgres,17),100);
349 rup->lastpasschange=strtoul(dbgetvalue(pgres,18),NULL,10);
350 rup->knownon=NULL;
351 rup->checkshd=NULL;
352 rup->stealcount=0;
353 rup->fakeuser=NULL;
354 addregusertohash(rup);
355
356 if (rup->ID > lastuserID) {
357 lastuserID=rup->ID;
358 }
359 }
360
361 dbclear(pgres);
362 }
363
364 void loadusersdone(DBConn *conn, void *arg) {
365 Error("chanserv",ERR_INFO,"Load users done (highest ID was %d)",lastuserID);
366 }
367
368 /*
369 * Channel loading functions
370 */
371
372 void loadsomechannels(DBConn *dbconn, void *arg) {
373 DBResult *pgres;
374 regchan *rcp;
375 int j;
376 chanindex *cip;
377 time_t now=time(NULL);
378
379 pgres=dbgetresult(dbconn);
380
381 if (!dbquerysuccessful(pgres)) {
382 Error("chanserv",ERR_ERROR,"Error loading channel DB");
383 return;
384 }
385
386 if (dbnumfields(pgres)!=27) {
387 Error("chanserv",ERR_ERROR,"Channel DB format error");
388 return;
389 }
390
391 while(dbfetchrow(pgres)) {
392 cip=findorcreatechanindex(dbgetvalue(pgres,1));
393 if (cip->exts[chanservext]) {
394 Error("chanserv",ERR_WARNING,"%s in database twice - this WILL cause problems later.",cip->name->content);
395 continue;
396 }
397 rcp=getregchan();
398 cip->exts[chanservext]=rcp;
399
400 rcp->ID=strtoul(dbgetvalue(pgres,0),NULL,10);
401 rcp->index=cip;
402 rcp->flags=strtoul(dbgetvalue(pgres,2),NULL,10);
403 rcp->status=0; /* Non-DB field */
404 rcp->lastbancheck=0;
405 rcp->lastcountersync=now;
406 rcp->lastpart=0;
407 rcp->bans=NULL;
408 rcp->forcemodes=strtoul(dbgetvalue(pgres,3),NULL,10);
409 rcp->denymodes=strtoul(dbgetvalue(pgres,4),NULL,10);
410 rcp->limit=strtoul(dbgetvalue(pgres,5),NULL,10);
411 rcp->autolimit=strtoul(dbgetvalue(pgres,6),NULL,10);
412 rcp->banstyle=strtoul(dbgetvalue(pgres,7),NULL,10);
413 rcp->created=strtoul(dbgetvalue(pgres,8),NULL,10);
414 rcp->lastactive=strtoul(dbgetvalue(pgres,9),NULL,10);
415 rcp->statsreset=strtoul(dbgetvalue(pgres,10),NULL,10);
416 rcp->banduration=strtoul(dbgetvalue(pgres,11),NULL,10);
417 rcp->founder=strtol(dbgetvalue(pgres,12),NULL,10);
418 rcp->addedby=strtol(dbgetvalue(pgres,13),NULL,10);
419 rcp->suspendby=strtol(dbgetvalue(pgres,14),NULL,10);
420 rcp->suspendtime=strtol(dbgetvalue(pgres,15),NULL,10);
421 rcp->chantype=strtoul(dbgetvalue(pgres,16),NULL,10);
422 rcp->totaljoins=strtoul(dbgetvalue(pgres,17),NULL,10);
423 rcp->tripjoins=strtoul(dbgetvalue(pgres,18),NULL,10);
424 rcp->maxusers=strtoul(dbgetvalue(pgres,19),NULL,10);
425 rcp->tripusers=strtoul(dbgetvalue(pgres,20),NULL,10);
426 rcp->welcome=getsstring(dbgetvalue(pgres,21),500);
427 rcp->topic=getsstring(dbgetvalue(pgres,22),TOPICLEN);
428 rcp->key=getsstring(dbgetvalue(pgres,23),KEYLEN);
429 rcp->suspendreason=getsstring(dbgetvalue(pgres,24),250);
430 rcp->comment=getsstring(dbgetvalue(pgres,25),250);
431 rcp->checksched=NULL;
432 rcp->ltimestamp=strtoul(dbgetvalue(pgres,26),NULL,10);
433 memset(rcp->regusers,0,REGCHANUSERHASHSIZE*sizeof(reguser *));
434
435 if (rcp->ID > lastchannelID)
436 lastchannelID=rcp->ID;
437
438 if (CIsAutoLimit(rcp))
439 rcp->limit=0;
440
441 for (j=0;j<CHANOPHISTORY;j++) {
442 rcp->chanopnicks[j][0]='\0';
443 rcp->chanopaccts[j]=0;
444 }
445 rcp->chanoppos=0;
446 }
447
448 dbclear(pgres);
449 }
450
451 void loadchannelsdone(DBConn *dbconn, void *arg) {
452 Error("chanserv",ERR_INFO,"Channel load done (highest ID was %d)",lastchannelID);
453 }
454
455 void loadchanusersinit(DBConn *dbconn, void *arg) {
456 int i;
457 chanindex *cip;
458 regchan *rcp;
459
460 allchans=(regchan **)malloc((lastchannelID+1)*sizeof(regchan *));
461 memset(allchans,0,(lastchannelID+1)*sizeof(regchan *));
462 for (i=0;i<CHANNELHASHSIZE;i++) {
463 for (cip=chantable[i];cip;cip=cip->next) {
464 if (cip->exts[chanservext]) {
465 rcp=(regchan *)cip->exts[chanservext];
466 allchans[rcp->ID]=rcp;
467 }
468 }
469 }
470 }
471
472 void loadsomechanusers(DBConn *dbconn, void *arg) {
473 DBResult *pgres;
474 regchanuser *rcup;
475 regchan *rcp;
476 reguser *rup;
477 authname *anp;
478 int uid,cid;
479 int total=0;
480
481 /* Set up the allchans array */
482 pgres=dbgetresult(dbconn);
483
484 if (!dbquerysuccessful(pgres)) {
485 Error("chanserv",ERR_ERROR,"Error loading chanusers.");
486 return;
487 }
488
489 if (dbnumfields(pgres)!=6) {
490 Error("chanserv",ERR_ERROR,"Chanusers format error");
491 return;
492 }
493
494 while(dbfetchrow(pgres)) {
495 uid=strtol(dbgetvalue(pgres,0),NULL,10);
496 cid=strtol(dbgetvalue(pgres,1),NULL,10);
497
498 if (!(anp=findauthname(uid)) || !(rup=anp->exts[chanservaext])) {
499 Error("chanserv",ERR_WARNING,"Skipping channeluser for unknown user %d",uid);
500 continue;
501 }
502
503 if (cid>lastchannelID || !(rcp=allchans[cid])) {
504 Error("chanserv",ERR_WARNING,"Skipping channeluser for unknown chan %d",cid);
505 continue;
506 }
507
508 if (rup==NULL || rcp==NULL) {
509 Error("chanserv",ERR_ERROR,"Can't add user %s on channel %s",
510 dbgetvalue(pgres,0),dbgetvalue(pgres,1));
511 } else {
512 rcup=getregchanuser();
513 rcup->user=rup;
514 rcup->chan=rcp;
515 rcup->flags=strtol(dbgetvalue(pgres,2),NULL,10);
516 rcup->changetime=strtol(dbgetvalue(pgres,3),NULL,10);
517 rcup->usetime=strtol(dbgetvalue(pgres,4),NULL,10);
518 rcup->info=getsstring(dbgetvalue(pgres,5),100);
519 addregusertochannel(rcup);
520 total++;
521 }
522 }
523
524 dbclear(pgres);
525 }
526
527 void loadchanusersdone(DBConn *dbconn, void *arg) {
528 Error("chanserv",ERR_INFO,"Channel user load done.");
529 }
530
531 void loadsomechanbans(DBConn *dbconn, void *arg) {
532 DBResult *pgres;
533 regban *rbp;
534 regchan *rcp;
535 int uid,cid,bid;
536 time_t expiry;
537 int total=0;
538
539 pgres=dbgetresult(dbconn);
540
541 if (!dbquerysuccessful(pgres)) {
542 Error("chanserv",ERR_ERROR,"Error loading bans.");
543 return;
544 }
545
546 if (dbnumfields(pgres)!=6) {
547 Error("chanserv",ERR_ERROR,"Ban format error");
548 return;
549 }
550
551 while(dbfetchrow(pgres)) {
552 bid=strtoul(dbgetvalue(pgres,0),NULL,10);
553 cid=strtoul(dbgetvalue(pgres,1),NULL,10);
554 uid=strtoul(dbgetvalue(pgres,2),NULL,10);
555 expiry=strtoul(dbgetvalue(pgres,4),NULL,10);
556
557 if (cid>lastchannelID || !(rcp=allchans[cid])) {
558 Error("chanserv",ERR_WARNING,"Skipping ban for unknown chan %d",cid);
559 continue;
560 }
561
562 rbp=getregban();
563 rbp->setby=uid;
564 rbp->ID=bid;
565 rbp->expiry=expiry;
566 rbp->reason=getsstring(dbgetvalue(pgres,5),200);
567 rbp->cbp=makeban(dbgetvalue(pgres,3));
568 rbp->next=rcp->bans;
569 rcp->bans=rbp;
570
571 total++;
572
573 if (bid>lastbanID)
574 lastbanID=bid;
575 }
576
577 dbclear(pgres);
578 }
579
580 void loadchanbansdone(DBConn *dbconn, void *arg) {
581 free(allchans);
582
583 Error("chanserv",ERR_INFO,"Channel ban load done, highest ID was %d",lastbanID);
584 }
585
586 void loadmessages() {
587 dbasyncquery(loadmessages_part1, NULL, "SELECT * from chanserv.languages");
588 }
589
590 void loadmessages_part1(DBConn *dbconn, void *arg) {
591 int i,j;
592 DBResult *pgres;
593
594 /* Firstly, clear up any stale messages */
595 for (i=0;i<MAXLANG;i++) {
596 if (cslanguages[i]) {
597 freesstring(cslanguages[i]->name);
598 free(cslanguages[i]);
599 }
600 for (j=0;j<MAXMESSAGES;j++) {
601 if (csmessages[i][j]) {
602 freesstring(csmessages[i][j]);
603 csmessages[i][j]=NULL;
604 }
605 }
606 }
607
608 pgres=dbgetresult(dbconn);
609
610 if (!dbquerysuccessful(pgres)) {
611 Error("chanserv",ERR_ERROR,"Error loading language list.");
612 return;
613 }
614
615 if (dbnumfields(pgres)!=3) {
616 Error("chanserv",ERR_ERROR,"Language list format error.");
617 return;
618 }
619
620 while(dbfetchrow(pgres)) {
621 j=strtol(dbgetvalue(pgres,0),NULL,10);
622 if (j<MAXLANG && j>=0) {
623 cslanguages[j]=(cslang *)malloc(sizeof(cslang));
624
625 strncpy(cslanguages[j]->code,dbgetvalue(pgres,1),2); cslanguages[j]->code[2]='\0';
626 cslanguages[j]->name=getsstring(dbgetvalue(pgres,2),30);
627 }
628 }
629
630 dbclear(pgres);
631
632 if (i>MAXLANG)
633 Error("chanserv",ERR_ERROR,"Found too many languages (%d > %d)",i,MAXLANG);
634
635 dbasyncquery(loadmessages_part2, NULL, "SELECT * from chanserv.messages");
636 }
637
638 void loadmessages_part2(DBConn *dbconn, void *arg) {
639 DBResult *pgres;
640 int j,k;
641
642 pgres=dbgetresult(dbconn);
643
644 if (!dbquerysuccessful(pgres)) {
645 Error("chanserv",ERR_ERROR,"Error loading message list.");
646 return;
647 }
648
649 if (dbnumfields(pgres)!=3) {
650 Error("chanserv",ERR_ERROR,"Message list format error.");
651 return;
652 }
653
654 while(dbfetchrow(pgres)) {
655 k=strtol(dbgetvalue(pgres,0),NULL,10);
656 j=strtol(dbgetvalue(pgres,1),NULL,10);
657
658 if (k<0 || k >= MAXLANG) {
659 Error("chanserv",ERR_WARNING,"Language ID out of range on message: %d",k);
660 continue;
661 }
662
663 if (j<0 || j >= MAXMESSAGES) {
664 Error("chanserv",ERR_WARNING,"Message ID out of range on message: %d",j);
665 continue;
666 }
667
668 csmessages[k][j]=getsstring(dbgetvalue(pgres,2),250);
669 }
670
671 dbclear(pgres);
672 }
673
674 void loadcommandsummary(Command *cmd) {
675 dbasyncquery(loadcommandsummary_real, (void *)cmd,
676 "SELECT languageID,summary from chanserv.help where lower(command) = lower('%s')",cmd->command->content);
677 }
678
679 void loadcommandsummary_real(DBConn *dbconn, void *arg) {
680 int i,j;
681 DBResult *pgres;
682 cmdsummary *cs;
683 Command *cmd=arg;
684
685 /* Clear up old text first */
686 cs=cmd->ext;
687 for (i=0;i<MAXLANG;i++) {
688 if (cs->bylang[i])
689 freesstring(cs->bylang[i]);
690 }
691
692 pgres=dbgetresult(dbconn);
693
694 if (!dbquerysuccessful(pgres)) {
695 Error("chanserv",ERR_ERROR,"Error loading command summary.");
696 return;
697 }
698
699 if (dbnumfields(pgres)!=2) {
700 Error("chanserv",ERR_ERROR,"Command summary format error.");
701 dbclear(pgres);
702 return;
703 }
704
705 while(dbfetchrow(pgres)) {
706 j=strtol(dbgetvalue(pgres,0),NULL,10);
707 if (j<MAXLANG && j>=0) {
708 cs->bylang[j]=getsstring(dbgetvalue(pgres,1),200);
709 }
710 }
711
712 dbclear(pgres);
713 }
714
715 void csdb_freestuff() {
716 int i;
717 chanindex *cip, *ncip;
718 regchan *rcp;
719 reguser *rup;
720 regchanuser *rcup;
721 regban *rbp;
722 maildomain *mdp;
723 maillock *mlp, *nmlp;
724
725 for (i=0;i<REGUSERHASHSIZE;i++) {
726 for (rup=regusernicktable[i];rup;rup=rup->nextbyname) {
727 freesstring(rup->email);
728 freesstring(rup->localpart);
729 freesstring(rup->lastemail);
730 freesstring(rup->lastuserhost);
731 freesstring(rup->suspendreason);
732 freesstring(rup->comment);
733 freesstring(rup->info);
734
735 for (rcup=rup->knownon;rcup;rcup=rcup->nextbyuser)
736 freesstring(rcup->info);
737 }
738 }
739
740 for (i=0;i<CHANNELHASHSIZE;i++) {
741 for (cip=chantable[i];cip;cip=ncip) {
742 ncip=cip->next;
743 if ((rcp=cip->exts[chanservext])) {
744 freesstring(rcp->welcome);
745 freesstring(rcp->topic);
746 freesstring(rcp->key);
747 freesstring(rcp->suspendreason);
748 freesstring(rcp->comment);
749 for (rbp=rcp->bans;rbp;rbp=rbp->next) {
750 freesstring(rbp->reason);
751 freechanban(rbp->cbp);
752 }
753 cip->exts[chanservext]=NULL;
754 releasechanindex(cip);
755 }
756 }
757 }
758
759 for (i=0; i<MAILDOMAINHASHSIZE; i++) {
760 for (mdp=maildomainnametable[i]; mdp; mdp=mdp->nextbyname)
761 freesstring(mdp->name);
762 }
763
764 for(mlp=maillocks;mlp;mlp=nmlp) {
765 nmlp=mlp->next;
766 freemaillock(mlp);
767 }
768 maillocks=NULL;
769 }
770
771 void loadsomemaildomains(DBConn *dbconn,void *arg) {
772 DBResult *pgres;
773 maildomain *mdp;
774 char *domain;
775 pgres=dbgetresult(dbconn);
776
777 if (!dbquerysuccessful(pgres)) {
778 Error("chanserv",ERR_ERROR,"Error loading maildomain DB");
779 return;
780 }
781
782 if (dbnumfields(pgres)!=5) {
783 Error("chanserv",ERR_ERROR,"Mail Domain DB format error");
784 dbclear(pgres);
785 return;
786 }
787 lastdomainID=0;
788
789 while(dbfetchrow(pgres)) {
790 domain=dbgetvalue(pgres,1);
791 mdp=findorcreatemaildomain(domain); //@@@ LEN
792
793 mdp->ID=strtoul(dbgetvalue(pgres,0),NULL,10);
794 mdp->limit=strtoul(dbgetvalue(pgres,2),NULL,10);
795 mdp->actlimit=strtoul(dbgetvalue(pgres,3),NULL,10);
796 mdp->flags=strtoul(dbgetvalue(pgres,4),NULL,10);
797
798 if (mdp->ID > lastdomainID) {
799 lastdomainID=mdp->ID;
800 }
801 }
802
803 dbclear(pgres);
804 }
805
806 void loadmaildomainsdone(DBConn *dbconn, void *arg) {
807 Error("chanserv",ERR_INFO,"Load Mail Domains done (highest ID was %d)",lastdomainID);
808 }
809
810 void loadsomemaillocks(DBConn *dbconn,void *arg) {
811 DBResult *pgres;
812 maillock *mlp;
813 pgres=dbgetresult(dbconn);
814
815 if (!dbquerysuccessful(pgres)) {
816 Error("chanserv",ERR_ERROR,"Error loading maillock DB");
817 return;
818 }
819
820 if (dbnumfields(pgres)!=5) {
821 Error("chanserv",ERR_ERROR,"Maillock DB format error");
822 dbclear(pgres);
823 return;
824 }
825 lastmaillockID=0;
826
827 while(dbfetchrow(pgres)) {
828 mlp=getmaillock();
829 mlp->id=strtoul(dbgetvalue(pgres,0),NULL,10);
830 mlp->pattern=getsstring(dbgetvalue(pgres,1), 300);
831 mlp->reason=getsstring(dbgetvalue(pgres,2), 300);
832 mlp->createdby=strtoul(dbgetvalue(pgres,3),NULL,10);
833 mlp->created=strtoul(dbgetvalue(pgres,4),NULL,10);
834 mlp->next=maillocks;
835 maillocks=mlp;
836
837 if (mlp->id > lastmaillockID)
838 lastmaillockID=mlp->id;
839 }
840
841 dbclear(pgres);
842 }
843
844 void loadmaillocksdone(DBConn *dbconn, void *arg) {
845 Error("chanserv",ERR_INFO,"Load Mail Locks done (highest ID was %d)",lastmaillockID);
846
847 chanservdb_ready=1;
848 triggerhook(HOOK_CHANSERV_DBLOADED, NULL);
849 }
850