]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/database/chanservdb.c
CHANSERV: Added explicit message when allowing opers to issue commands on
[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
15 #include <string.h>
16 #include <stdio.h>
17 #include <sys/poll.h>
18 #include <stdarg.h>
19
20 int chanservdb_ready;
21
22 regchan **allchans;
23 maillock *maillocks;
24
25 int chanservext;
26 int chanservaext;
27
28 unsigned int lastchannelID;
29 unsigned int lastuserID;
30 unsigned int lastbanID;
31 unsigned int lastdomainID;
32 unsigned int lastmaillockID;
33
34 /* Local prototypes */
35 void csdb_handlestats(int hooknum, void *arg);
36 void loadmessages_part1(DBConn *, void *);
37 void loadmessages_part2(DBConn *, void *);
38 void loadcommandsummary_real(DBConn *, void *);
39
40 /* User loading functions */
41 void loadsomeusers(DBConn *, void *);
42 void loadusersdone(DBConn *, void *);
43
44 /* Channel loading functions */
45 void loadsomechannels(DBConn *, void *);
46 void loadchannelsdone(DBConn *, void *);
47
48 /* Chanuser loading functions */
49 void loadchanusersinit(DBConn *, void *);
50 void loadsomechanusers(DBConn *, void *);
51 void loadchanusersdone(DBConn *, void *);
52
53 /* Chanban loading functions */
54 void loadsomechanbans(DBConn *, void *);
55 void loadchanbansdone(DBConn *, void *);
56
57 /* Mail Domain loading functions */
58 void loadsomemaildomains(DBConn *, void *);
59 void loadmaildomainsdone(DBConn *, void *);
60
61 /* Mail lock loading functions */
62 void loadsomemaillocks(DBConn *, void *);
63 void loadmaillocksdone(DBConn *, void *);
64
65 /* Free sstrings in the structures */
66 void csdb_freestuff();
67
68 static void setuptables() {
69 /* Set up the tables */
70 /* User table */
71 dbattach("chanserv");
72 dbcreatequery("CREATE TABLE chanserv.users ("
73 "ID INT NOT NULL,"
74 "username VARCHAR(16) NOT NULL,"
75 "created INT NOT NULL,"
76 "lastauth INT NOT NULL,"
77 "lastemailchng INT NOT NULL,"
78 "flags INT NOT NULL,"
79 "language INT NOT NULL,"
80 "suspendby INT NOT NULL,"
81 "suspendexp INT NOT NULL,"
82 "suspendtime INT NOT NULL,"
83 "lockuntil INT NOT NULL,"
84 "password VARCHAR(11) NOT NULL,"
85 "email VARCHAR(100),"
86 "lastemail VARCHAR(100),"
87 "lastuserhost VARCHAR(75),"
88 "suspendreason VARCHAR(250),"
89 "comment VARCHAR(250),"
90 "info VARCHAR(100),"
91 "lastpasschng INT NOT NULL,"
92 "PRIMARY KEY (ID))");
93
94 dbcreatequery("CREATE INDEX user_username_index ON chanserv.users (username)");
95
96 /* Channel table */
97 dbcreatequery("CREATE TABLE chanserv.channels ("
98 "ID INT NOT NULL,"
99 "name VARCHAR(250) NOT NULL,"
100 "flags INT NOT NULL,"
101 "forcemodes INT NOT NULL,"
102 "denymodes INT NOT NULL,"
103 "chanlimit INT NOT NULL,"
104 "autolimit INT NOT NULL,"
105 "banstyle INT NOT NULL,"
106 "created INT NOT NULL,"
107 "lastactive INT NOT NULL,"
108 "statsreset INT NOT NULL,"
109 "banduration INT NOT NULL,"
110 "founder INT NOT NULL,"
111 "addedby INT NOT NULL,"
112 "suspendby INT NOT NULL,"
113 "suspendtime INT NOT NULL,"
114 "chantype SMALLINT NOT NULL,"
115 "totaljoins INT NOT NULL,"
116 "tripjoins INT NOT NULL,"
117 "maxusers INT NOT NULL,"
118 "tripusers INT NOT NULL,"
119 "welcome VARCHAR(500),"
120 "topic VARCHAR(250),"
121 "chankey VARCHAR(23),"
122 "suspendreason VARCHAR(250),"
123 "comment VARCHAR(250),"
124 "lasttimestamp INT,"
125 "PRIMARY KEY (ID))");
126
127 /* Chanuser table */
128 dbcreatequery("CREATE TABLE chanserv.chanusers ("
129 "userID INT NOT NULL,"
130 "channelID INT NOT NULL,"
131 "flags INT NOT NULL,"
132 "changetime INT NOT NULL,"
133 "usetime INT NOT NULL,"
134 "info VARCHAR(100) NOT NULL,"
135 "PRIMARY KEY (userID, channelID))");
136
137 dbcreatequery("CREATE INDEX chanusers_userID_index on chanserv.chanusers (userID)");
138 dbcreatequery("CREATE INDEX chanusers_channelID_index on chanserv.chanusers (channelID)");
139
140 dbcreatequery("CREATE TABLE chanserv.bans ("
141 "banID INT NOT NULL," /* Unique number for the ban to make
142 DELETEs process in finite time.. */
143 "channelID INT NOT NULL,"
144 "userID INT NOT NULL," /* Who set the ban.. */
145 "hostmask VARCHAR(100) NOT NULL," /* needs to be at least USERLEN+NICKLEN+HOSTLEN+2 */
146 "expiry INT NOT NULL,"
147 "reason VARCHAR(200),"
148 "PRIMARY KEY(banID))");
149
150 dbcreatequery("CREATE INDEX bans_channelID_index on chanserv.bans (channelID)");
151
152 dbcreatequery("CREATE TABLE chanserv.languages ("
153 "languageID INT NOT NULL,"
154 "code VARCHAR(2) NOT NULL,"
155 "name VARCHAR(30) NOT NULL)");
156
157 dbcreatequery("CREATE TABLE chanserv.messages ("
158 "languageID INT NOT NULL,"
159 "messageID INT NOT NULL,"
160 "message VARCHAR(250) NOT NULL,"
161 "PRIMARY KEY (languageID, messageID))");
162
163 dbcreatequery("CREATE TABLE chanserv.help ("
164 "commandID INT NOT NULL,"
165 "command VARCHAR(30) NOT NULL,"
166 "languageID INT NOT NULL,"
167 "summary VARCHAR(200) NOT NULL,"
168 "fullinfo TEXT NOT NULL,"
169 "PRIMARY KEY (commandID, languageID))");
170
171 dbcreatequery("CREATE TABLE chanserv.email ("
172 "userID INT NOT NULL,"
173 "emailtype INT NOT NULL,"
174 "prevEmail VARCHAR(100),"
175 "mailID SERIAL,"
176 "PRIMARY KEY (mailID))");
177
178 dbcreatequery("CREATE TABLE chanserv.maildomain ("
179 "ID INT NOT NULL,"
180 "name VARCHAR NOT NULL,"
181 "domainlimit INT NOT NULL,"
182 "actlimit INT NOT NULL,"
183 "flags INT NOT NULL,"
184 "PRIMARY KEY (ID))");
185
186 dbcreatequery("CREATE TABLE chanserv.authhistory ("
187 "userID INT NOT NULL,"
188 "nick VARCHAR(15) NOT NULL,"
189 "username VARCHAR(10) NOT NULL,"
190 "host VARCHAR(63) NOT NULL,"
191 "authtime INT NOT NULL,"
192 "disconnecttime INT NOT NULL,"
193 "numeric INT NOT NULL,"
194 "quitreason VARCHAR(100) ,"
195 "PRIMARY KEY (userID, authtime))");
196
197 dbcreatequery("CREATE INDEX authhistory_userID_index on chanserv.authhistory(userID)");
198 dbcreatequery("CREATE TABLE chanserv.chanlevhistory ("
199 "userID INT NOT NULL,"
200 "channelID INT NOT NULL,"
201 "targetID INT NOT NULL,"
202 "changetime INT NOT NULL,"
203 "authtime INT NOT NULL,"
204 "oldflags INT NOT NULL,"
205 "newflags INT NOT NULL)");
206
207 dbcreatequery("CREATE INDEX chanlevhistory_userID_index on chanserv.chanlevhistory(userID)");
208 dbcreatequery("CREATE INDEX chanlevhistory_channelID_index on chanserv.chanlevhistory(channelID)");
209 dbcreatequery("CREATE INDEX chanlevhistory_targetID_index on chanserv.chanlevhistory(targetID)");
210
211 dbcreatequery("CREATE TABLE chanserv.accounthistory ("
212 "userID INT NOT NULL,"
213 "changetime INT NOT NULL,"
214 "authtime INT NOT NULL,"
215 "oldpassword VARCHAR(11),"
216 "newpassword VARCHAR(11),"
217 "oldemail VARCHAR(100),"
218 "newemail VARCHAR(100),"
219 "PRIMARY KEY (userID, changetime))");
220
221 dbcreatequery("CREATE INDEX accounthistory_userID_index on chanserv.accounthistory(userID)");
222
223 dbcreatequery("CREATE TABLE chanserv.maillocks ("
224 "ID INT NOT NULL,"
225 "pattern VARCHAR NOT NULL,"
226 "reason VARCHAR NOT NULL,"
227 "createdby INT NOT NULL,"
228 "created INT NOT NULL,"
229 "PRIMARY KEY (ID))");
230 }
231
232 void _init() {
233 chanservext=registerchanext("chanserv");
234 chanservaext=registerauthnameext("chanserv",1);
235
236 /* Set up the allocators and hashes */
237 chanservallocinit();
238 chanservhashinit();
239
240 /* And the messages */
241 initmessages();
242
243 if (dbconnected() && (chanservext!=-1) && (chanservaext!=-1)) {
244 registerhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
245
246 setuptables();
247
248 lastuserID=lastchannelID=lastdomainID=0;
249
250 dbloadtable("chanserv.users",NULL,loadsomeusers,loadusersdone);
251 dbloadtable("chanserv.channels",NULL,loadsomechannels,loadchannelsdone);
252 dbloadtable("chanserv.chanusers",loadchanusersinit,loadsomechanusers,loadchanusersdone);
253 dbloadtable("chanserv.bans",NULL,loadsomechanbans,loadchanbansdone);
254 dbloadtable("chanserv.maildomain",NULL, loadsomemaildomains,loadmaildomainsdone);
255 dbloadtable("chanserv.maillocks",NULL, loadsomemaillocks,loadmaillocksdone);
256
257 loadmessages();
258 }
259 }
260
261 void _fini() {
262 deregisterhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
263
264 csdb_freestuff();
265
266 if (chanservext!=-1)
267 releasechanext(chanservext);
268
269 if (chanservaext!=-1)
270 releaseauthnameext(chanservaext);
271
272 nsfreeall(POOL_CHANSERVDB);
273 dbdetach("chanserv");
274 }
275
276 void csdb_handlestats(int hooknum, void *arg) {
277 /* long level=(long)arg; */
278
279 /* Keeping options open here */
280 }
281
282 void chanservdbclose() {
283
284 deregisterhook(HOOK_CORE_STATSREQUEST, csdb_handlestats);
285
286 }
287
288 /*
289 * loadsomeusers():
290 * Loads some users in from the SQL DB
291 */
292
293 void loadsomeusers(DBConn *dbconn, void *arg) {
294 DBResult *pgres;
295 reguser *rup;
296 char *local;
297 char mailbuf[1024];
298
299 pgres=dbgetresult(dbconn);
300
301 if (!dbquerysuccessful(pgres)) {
302 Error("chanserv",ERR_ERROR,"Error loading user DB");
303 return;
304 }
305
306 if (dbnumfields(pgres)!=19) {
307 Error("chanserv",ERR_ERROR,"User DB format error");
308 return;
309 }
310
311 while(dbfetchrow(pgres)) {
312 rup=getreguser();
313 rup->status=0;
314 rup->ID=strtoul(dbgetvalue(pgres,0),NULL,10);
315 strncpy(rup->username,dbgetvalue(pgres,1),NICKLEN); rup->username[NICKLEN]='\0';
316 rup->created=strtoul(dbgetvalue(pgres,2),NULL,10);
317 rup->lastauth=strtoul(dbgetvalue(pgres,3),NULL,10);
318 rup->lastemailchange=strtoul(dbgetvalue(pgres,4),NULL,10);
319 rup->flags=strtoul(dbgetvalue(pgres,5),NULL,10);
320 rup->languageid=strtoul(dbgetvalue(pgres,6),NULL,10);
321 rup->suspendby=strtoul(dbgetvalue(pgres,7),NULL,10);
322 rup->suspendexp=strtoul(dbgetvalue(pgres,8),NULL,10);
323 rup->suspendtime=strtoul(dbgetvalue(pgres,9),NULL,10);
324 rup->lockuntil=strtoul(dbgetvalue(pgres,10),NULL,10);
325 strncpy(rup->password,dbgetvalue(pgres,11),PASSLEN); rup->password[PASSLEN]='\0';
326 rup->email=getsstring(dbgetvalue(pgres,12),100);
327 if (rup->email) {
328 rup->domain=findorcreatemaildomain(rup->email->content);
329 addregusertomaildomain(rup, rup->domain);
330
331 strlcpy(mailbuf, rup->email->content, sizeof(mailbuf));
332 if((local=strchr(mailbuf, '@'))) {
333 *(local++)='\0';
334 rup->localpart=getsstring(mailbuf,EMAILLEN);
335 } else {
336 rup->localpart=NULL;
337 }
338 } else {
339 rup->domain=NULL;
340 rup->localpart=NULL;
341 }
342 rup->lastemail=getsstring(dbgetvalue(pgres,13),100);
343 rup->lastuserhost=getsstring(dbgetvalue(pgres,14),75);
344 rup->suspendreason=getsstring(dbgetvalue(pgres,15),250);
345 rup->comment=getsstring(dbgetvalue(pgres,16),250);
346 rup->info=getsstring(dbgetvalue(pgres,17),100);
347 rup->lastpasschange=strtoul(dbgetvalue(pgres,18),NULL,10);
348 rup->knownon=NULL;
349 rup->checkshd=NULL;
350 rup->stealcount=0;
351 rup->fakeuser=NULL;
352 addregusertohash(rup);
353
354 if (rup->ID > lastuserID) {
355 lastuserID=rup->ID;
356 }
357 }
358
359 dbclear(pgres);
360 }
361
362 void loadusersdone(DBConn *conn, void *arg) {
363 Error("chanserv",ERR_INFO,"Load users done (highest ID was %d)",lastuserID);
364 }
365
366 /*
367 * Channel loading functions
368 */
369
370 void loadsomechannels(DBConn *dbconn, void *arg) {
371 DBResult *pgres;
372 regchan *rcp;
373 int j;
374 chanindex *cip;
375 time_t now=time(NULL);
376
377 pgres=dbgetresult(dbconn);
378
379 if (!dbquerysuccessful(pgres)) {
380 Error("chanserv",ERR_ERROR,"Error loading channel DB");
381 return;
382 }
383
384 if (dbnumfields(pgres)!=27) {
385 Error("chanserv",ERR_ERROR,"Channel DB format error");
386 return;
387 }
388
389 while(dbfetchrow(pgres)) {
390 cip=findorcreatechanindex(dbgetvalue(pgres,1));
391 if (cip->exts[chanservext]) {
392 Error("chanserv",ERR_WARNING,"%s in database twice - this WILL cause problems later.",cip->name->content);
393 continue;
394 }
395 rcp=getregchan();
396 cip->exts[chanservext]=rcp;
397
398 rcp->ID=strtoul(dbgetvalue(pgres,0),NULL,10);
399 rcp->index=cip;
400 rcp->flags=strtoul(dbgetvalue(pgres,2),NULL,10);
401 rcp->status=0; /* Non-DB field */
402 rcp->lastbancheck=0;
403 rcp->lastcountersync=now;
404 rcp->lastpart=0;
405 rcp->bans=NULL;
406 rcp->forcemodes=strtoul(dbgetvalue(pgres,3),NULL,10);
407 rcp->denymodes=strtoul(dbgetvalue(pgres,4),NULL,10);
408 rcp->limit=strtoul(dbgetvalue(pgres,5),NULL,10);
409 rcp->autolimit=strtoul(dbgetvalue(pgres,6),NULL,10);
410 rcp->banstyle=strtoul(dbgetvalue(pgres,7),NULL,10);
411 rcp->created=strtoul(dbgetvalue(pgres,8),NULL,10);
412 rcp->lastactive=strtoul(dbgetvalue(pgres,9),NULL,10);
413 rcp->statsreset=strtoul(dbgetvalue(pgres,10),NULL,10);
414 rcp->banduration=strtoul(dbgetvalue(pgres,11),NULL,10);
415 rcp->founder=strtol(dbgetvalue(pgres,12),NULL,10);
416 rcp->addedby=strtol(dbgetvalue(pgres,13),NULL,10);
417 rcp->suspendby=strtol(dbgetvalue(pgres,14),NULL,10);
418 rcp->suspendtime=strtol(dbgetvalue(pgres,15),NULL,10);
419 rcp->chantype=strtoul(dbgetvalue(pgres,16),NULL,10);
420 rcp->totaljoins=strtoul(dbgetvalue(pgres,17),NULL,10);
421 rcp->tripjoins=strtoul(dbgetvalue(pgres,18),NULL,10);
422 rcp->maxusers=strtoul(dbgetvalue(pgres,19),NULL,10);
423 rcp->tripusers=strtoul(dbgetvalue(pgres,20),NULL,10);
424 rcp->welcome=getsstring(dbgetvalue(pgres,21),500);
425 rcp->topic=getsstring(dbgetvalue(pgres,22),TOPICLEN);
426 rcp->key=getsstring(dbgetvalue(pgres,23),KEYLEN);
427 rcp->suspendreason=getsstring(dbgetvalue(pgres,24),250);
428 rcp->comment=getsstring(dbgetvalue(pgres,25),250);
429 rcp->checksched=NULL;
430 rcp->ltimestamp=strtoul(dbgetvalue(pgres,26),NULL,10);
431 memset(rcp->regusers,0,REGCHANUSERHASHSIZE*sizeof(reguser *));
432
433 if (rcp->ID > lastchannelID)
434 lastchannelID=rcp->ID;
435
436 if (CIsAutoLimit(rcp))
437 rcp->limit=0;
438
439 for (j=0;j<CHANOPHISTORY;j++) {
440 rcp->chanopnicks[j][0]='\0';
441 rcp->chanopaccts[j]=0;
442 }
443 rcp->chanoppos=0;
444 }
445
446 dbclear(pgres);
447 }
448
449 void loadchannelsdone(DBConn *dbconn, void *arg) {
450 Error("chanserv",ERR_INFO,"Channel load done (highest ID was %d)",lastchannelID);
451 }
452
453 void loadchanusersinit(DBConn *dbconn, void *arg) {
454 int i;
455 chanindex *cip;
456 regchan *rcp;
457
458 allchans=(regchan **)malloc((lastchannelID+1)*sizeof(regchan *));
459 memset(allchans,0,(lastchannelID+1)*sizeof(regchan *));
460 for (i=0;i<CHANNELHASHSIZE;i++) {
461 for (cip=chantable[i];cip;cip=cip->next) {
462 if (cip->exts[chanservext]) {
463 rcp=(regchan *)cip->exts[chanservext];
464 allchans[rcp->ID]=rcp;
465 }
466 }
467 }
468 }
469
470 void loadsomechanusers(DBConn *dbconn, void *arg) {
471 DBResult *pgres;
472 regchanuser *rcup;
473 regchan *rcp;
474 reguser *rup;
475 authname *anp;
476 int uid,cid;
477 int total=0;
478
479 /* Set up the allchans array */
480 pgres=dbgetresult(dbconn);
481
482 if (!dbquerysuccessful(pgres)) {
483 Error("chanserv",ERR_ERROR,"Error loading chanusers.");
484 return;
485 }
486
487 if (dbnumfields(pgres)!=6) {
488 Error("chanserv",ERR_ERROR,"Chanusers format error");
489 return;
490 }
491
492 while(dbfetchrow(pgres)) {
493 uid=strtol(dbgetvalue(pgres,0),NULL,10);
494 cid=strtol(dbgetvalue(pgres,1),NULL,10);
495
496 if (!(anp=findauthname(uid)) || !(rup=anp->exts[chanservaext])) {
497 Error("chanserv",ERR_WARNING,"Skipping channeluser for unknown user %d",uid);
498 continue;
499 }
500
501 if (cid>lastchannelID || !(rcp=allchans[cid])) {
502 Error("chanserv",ERR_WARNING,"Skipping channeluser for unknown chan %d",cid);
503 continue;
504 }
505
506 if (rup==NULL || rcp==NULL) {
507 Error("chanserv",ERR_ERROR,"Can't add user %s on channel %s",
508 dbgetvalue(pgres,0),dbgetvalue(pgres,1));
509 } else {
510 rcup=getregchanuser();
511 rcup->user=rup;
512 rcup->chan=rcp;
513 rcup->flags=strtol(dbgetvalue(pgres,2),NULL,10);
514 rcup->changetime=strtol(dbgetvalue(pgres,3),NULL,10);
515 rcup->usetime=strtol(dbgetvalue(pgres,4),NULL,10);
516 rcup->info=getsstring(dbgetvalue(pgres,5),100);
517 addregusertochannel(rcup);
518 total++;
519 }
520 }
521
522 dbclear(pgres);
523 }
524
525 void loadchanusersdone(DBConn *dbconn, void *arg) {
526 Error("chanserv",ERR_INFO,"Channel user load done.");
527 }
528
529 void loadsomechanbans(DBConn *dbconn, void *arg) {
530 DBResult *pgres;
531 regban *rbp;
532 regchan *rcp;
533 int uid,cid,bid;
534 time_t expiry,now;
535 int total=0;
536
537 pgres=dbgetresult(dbconn);
538
539 if (!dbquerysuccessful(pgres)) {
540 Error("chanserv",ERR_ERROR,"Error loading bans.");
541 return;
542 }
543
544 if (dbnumfields(pgres)!=6) {
545 Error("chanserv",ERR_ERROR,"Ban format error");
546 return;
547 }
548
549 now=time(NULL);
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