00001
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "services.h"
00047 #include "nickserv.h"
00048 #include "chanserv.h"
00049 #include "db.h"
00050 #include "hash/md5pw.h"
00051 #include "memoserv.h"
00052 #include "macro.h"
00053 #include "hash.h"
00054 #include "queue.h"
00055 #include "log.h"
00056 #include "infoserv.h"
00057
00058
00059 #define NS_DIR "nickserv/"
00060 #define CS_DIR "chanserv/"
00061 #define OS_DIR "operserv/"
00062 #define MS_DIR "memoserv/"
00063 #define IS_DIR "infoserv/"
00064
00065 #define NS_DB NS_DIR"nickserv.db"
00066 #define CS_DB CS_DIR"chanserv.db"
00067 #define MS_DB MS_DIR"memoserv.db"
00068 #define TRG_DB OS_DIR"trigger.db"
00069 #define AKI_DB OS_DIR"akill.db"
00070 #define IS_DB IS_DIR"infoserv.db"
00071
00072 extern RegId top_regnick_idnum;
00073
00074 #ifdef REQ_EMAIL
00075 # error REQ_EMAIL: does not work
00076 #endif
00077
00078 static char cryptstr[PASSLEN + 2];
00085 static char dbLine[2048];
00091 parse_t state;
00092
00093 void AppendBuffer(char **p, const char *);
00094 char *str_dup(const char*);
00095
00101 void unexpected_eof( const char* file_name )
00102 {
00103 fprintf(stderr, "Unexpected EOF: %s\n", file_name);
00104 logDump(corelog, "Unexpected EOF: %s", file_name);
00105 sshutdown(-1);
00106 }
00107
00108
00113 static char *dbReadString(FILE *fp)
00114 {
00115 char tempLine[125], *p = NULL, *y;
00116 int fin = 0, firstLn = 0;
00117
00118 while(!fin && sfgets(tempLine, 124, db.is)) {
00119 y = strrchr(tempLine, '~');
00120 assert(y != NULL);
00121 *y = '\0';
00122
00123 if (y[1] == '$')
00124 fin = 1;
00125
00126 strcat(tempLine, "\n");
00127 if (*tempLine != '\n')
00128 AppendBuffer(&p, tempLine);
00129 firstLn = 0;
00130 *y = '~';
00131 }
00132 if (p && *p)
00133 p[strlen(p) - 1] = '\0';
00134
00135 return p;
00136 }
00137
00138
00144 static void dbWriteString(FILE *fp, const char *istr)
00145 {
00146 char *p, *str;
00147 parse_t lineSplit;
00148
00149 str = str_dup(istr);
00150 assert(parse_init(&lineSplit, str) == 0);
00151 lineSplit.delim = '\n';
00152
00153 while((p = parse_getarg(&lineSplit))) {
00154 fprintf(fp, "%s~\n", p);
00155 }
00156 fprintf(fp, "~$\n");
00157 parse_cleanup(&lineSplit);
00158 FREE(str);
00159 }
00160
00164 void saveNickData(void)
00165 {
00166 RegNickList *nl;
00167 nAccessList *accitem;
00168 int x = 0, bucket;
00169
00170 db.ns = fopen(NS_DB, "w");
00171
00172 if (db.ns == NULL) {
00173 sSend(":%s GOPER :ERROR: Unable to save NickServ database fopen failed: %s", myname, strerror(errno));
00174 logDump(corelog, "Unable to save NickServ database: fopen: %s", strerror(errno));
00175 return;
00176 }
00177
00178 fprintf(db.ns, "version 3\n");
00179
00180 for (bucket = 0; bucket < NICKHASHSIZE; bucket++) {
00181 nl = LIST_FIRST(&RegNickHash[bucket]);
00182 while (nl != NULL) {
00183
00184 fprintf(db.ns, "nick ");
00185 if (nl->user[0] == '\0')
00186 fprintf(db.ns, "%s . %s ", nl->nick, nl->host);
00187 else
00188 fprintf(db.ns, "%s %s %s ", nl->nick, nl->user, nl->host);
00189
00190 if (!(nl->flags & NENCRYPT))
00191 {
00192 strcpy(cryptstr, (char *)nl->password);
00193 xorit(cryptstr);
00194 fprintf(db.ns, "@%s ", cryptstr);
00195 }
00196 else {
00197 unsigned char *p;
00198
00199
00200 p = toBase64(nl->password, 16);
00201 fprintf(db.ns, "$%s ", p);
00202 FREE(p);
00203 }
00204
00205 fprintf(db.ns, "%lu ", (unsigned long)nl->timestamp);
00206 fprintf(db.ns, "%lu ", (unsigned long)nl->timereg);
00207 fprintf(db.ns, "%i %X*%X\n", nl->flags, nl->regnum.a, nl->regnum.b);
00208
00209
00210 fprintf(db.ns, "is %ld\n", nl->is_readtime);
00211
00212 #ifdef REQ_EMAIL
00213 if (!(nl->flags & NACTIVE) || (nl->flags & NDEACC))
00214 fprintf(db.ns, "akey %lu\n", nl->email_key);
00215 #endif
00216 if (nl->chpw_key)
00217 fprintf(db.ns, "chkey %X\n", nl->chpw_key);
00218 if (nl->url != NULL)
00219 fprintf(db.ns, "url %s %s\n", nl->nick, nl->url);
00220 #ifdef TRACK_GECOS
00221 if (nl->gecos != NULL)
00222 fprintf(db.ns, "gecos :%s\n", nl->gecos);
00223 #endif
00224
00225 if (nl->email[0] && strcmp(nl->email, "(none)"))
00226 fprintf(db.ns, "email %s %s\n", nl->nick, nl->email);
00227
00228 if ((nl->opflags & ~(OROOT | OSERVOP)))
00229 fprintf(db.ns, "oper %s %lu 0 0\n", nl->nick, nl->opflags);
00230
00231 if ((nl->flags & NMARK) && nl->markby)
00232 fprintf(db.ns, "markby %s %s\n", nl->nick, nl->markby);
00233
00234 if (nl->idtime != DEF_NDELAY)
00235 fprintf(db.ns, "idtime %s %i\n", nl->nick, nl->idtime);
00236
00237 for (accitem = LIST_FIRST(&nl->acl); accitem;
00238 accitem = LIST_NEXT(accitem, al_lst))
00239 fprintf(db.ns, "access %s %s\n", nl->nick, accitem->mask);
00240 x++;
00241 fflush(db.ns);
00242 #ifdef DBDEBUG
00243 sSend(":%s PRIVMSG " DEBUGCHAN " :Saved nick data (%s)",
00244 NickServ, nl->nick);
00245 #endif
00246 nl = LIST_NEXT(nl, rn_lst);
00247 }
00248 }
00249 fprintf(db.ns, "done\n");
00250 fflush(db.ns);
00251 fclose(db.ns);
00252 #ifdef GLOBOPS_TIMED_MSGS
00253 sSend(":%s GLOBOPS :Completed save(%i)", NickServ, x);
00254 #else
00255 sSend(":%s PRIVMSG " LOGCHAN " :Completed save(%i)", NickServ, x);
00256 #endif
00257 }
00258
00262 void readNickData()
00263 {
00264 RegNickList *rnl = NULL;
00265 char *command, *tmpp;
00266 unsigned char *tmpup;
00267 int done = 0, db_version = 1;
00268 int line_num = 0, do_enc = 0;
00269
00270 #ifdef REQ_EMAIL
00271 readRegData();
00272 #endif
00273
00274 db.ns = fopen(NS_DB, "r");
00275
00276 if (db.ns == NULL) {
00277 logDump(corelog, "Unable to open " NS_DB ": %s", strerror(errno));
00278 return;
00279 }
00280
00281 while (!done) {
00282 if (!(sfgets(dbLine, 1024, db.ns))) {
00283 if (!done) {
00284 unexpected_eof(NS_DB);
00285 }
00286 done = 1;
00287 fclose(db.ns);
00288 return;
00289 }
00290
00291 line_num++;
00292
00293 if (parse_init(&state, dbLine) != 0) {
00295 abort();
00296 }
00297
00298 command = parse_getarg(&state);
00299 if (strcmp(command, "version") == 0) {
00300 tmpp = parse_getarg(&state);
00301 assert(tmpp);
00302
00303 if (tmpp)
00304 db_version = atoi(tmpp);
00305 }
00306 else
00307 if (strcmp(command, "nick") == 0) {
00308 rnl = (RegNickList *) oalloc(sizeof(RegNickList));
00309 char *sNick, *sUser, *sHost, *sPass;
00310
00311 sNick = parse_getarg(&state);
00312 sUser = parse_getarg(&state);
00313 sHost = parse_getarg(&state);
00314 sPass = parse_getarg(&state);
00315
00316 if (strlen(sNick) >= NICKLEN) {
00317 fprintf(stderr,
00318 NS_DB ":%d: " " Nickname '%.80s' exceeds "
00319 " NICKLEN.\n", line_num, sNick);
00320 sshutdown(-1);
00321 }
00322
00323 strcpy(rnl->nick, sNick);
00324 strncpyzt(rnl->user, sUser, USERLEN);
00325 SetDynBuffer(&rnl->host, sHost);
00326
00327 if (db_version < 2)
00328 {
00329 if (strlen(sPass) > PASSLEN) {
00330 fprintf(stderr,
00331 NS_DB ":%d: " " Password for nick '%s' "
00332 " exceeds PASSLEN.\n", line_num, sNick);
00333 sshutdown(-1);
00334 }
00335
00336 strcpy((char *)rnl->password, xorit(sPass));
00337 }
00338 else {
00339 char encType = *sPass;
00340
00341 if (encType == '@') {
00342 if (strlen(sPass+1) > PASSLEN) {
00343 fprintf(stderr,
00344 NS_DB ":%d: " " Password for nick '%s' "
00345 " exceeds PASSLEN.\n", line_num, sNick);
00346 sshutdown(-1);
00347 }
00348
00349 strcpy((char *)rnl->password, xorit(sPass + 1));
00350 do_enc = 0;
00351 }
00352 else if (encType == '$') {
00353 int q, len;
00354
00355 tmpup = fromBase64(sPass + 1, &len);
00356 assert(tmpup);
00357
00358 for(q = 0; q < 16; q++)
00359 rnl->password[q] = tmpup[q];
00360 do_enc = 1;
00361 FREE(tmpup);
00362 }
00363 else
00364 rnl->password[0] = '\0';
00365 }
00366
00367 rnl->timestamp = (time_t) atol(parse_getarg(&state));
00368 rnl->timereg = (time_t) atol(parse_getarg(&state));
00369 rnl->flags = atoi(parse_getarg(&state));
00370
00371 if (db_version >= 3) {
00372 const char *idString = parse_getarg(&state);
00373 int av, bv;
00374
00375 sscanf(idString, "%X*%X", &av, &bv);
00376 rnl->regnum.SetDirect(top_regnick_idnum, av, bv);
00377 }
00378 else {
00379 rnl->regnum.SetNext(top_regnick_idnum);
00380 }
00381
00382 if (do_enc)
00383 rnl->flags |= NENCRYPT;
00384 else
00385 rnl->flags &= ~NENCRYPT;
00386
00387 rnl->opflags = 0;
00388 rnl->idtime = DEF_NDELAY;
00389 ADD_MEMO_BOX(rnl);
00390 addRegNick(rnl);
00391 } else if (strcmp(command, "is") == 0) {
00392 char *data = parse_getarg(&state);
00393 if (rnl && data)
00394 rnl->is_readtime = atol(data);
00395 } else if (strcmp(command, "oper") == 0) {
00396 char *opflags_s;
00397 if (rnl && (rnl == getRegNickData(parse_getarg(&state)))) {
00398 if ((opflags_s = parse_getarg(&state)))
00399 rnl->opflags |=
00400 (strtoul(opflags_s, (char **)0, 10) &
00401 ~(OROOT | OSERVOP));
00402 if (rnl->opflags)
00403 addOpData(rnl);
00404 }
00405 } else if (strcmp(command, "url") == 0) {
00406 if (rnl && (rnl == getRegNickData(parse_getarg(&state))))
00407 {
00408 rnl->url = strdup(parse_getarg(&state));
00409 if (strlen(rnl->url) > (URLLEN - 1))
00410 rnl->url[URLLEN - 1] = '\0';
00411 }
00412 } else if (strcmp(command, "gecos") == 0) {
00413 #ifdef TRACK_GECOS
00414 char *gecos = parse_getallargs(&state);
00415 if (gecos != NULL)
00416 rnl->gecos = strdup(gecos);
00417 #endif
00418 } else if (strcmp(command, "akey") == 0) {
00419 #ifdef REQ_EMAIL
00420 if (rnl)
00421 rnl->email_key = atoi(parse_getarg(&state));
00422 #endif
00423 } else if (strcmp(command, "chkey") == 0) {
00424 char *tmpp = parse_getarg(&state);
00425 if (rnl && tmpp)
00426 rnl->chpw_key = strtoul(tmpp, (char **)0, 16);
00427 } else if (strcmp(command, "markby") == 0) {
00428 char *mby;
00429
00430 rnl = getRegNickData(parse_getarg(&state));
00431 if (!rnl || !(mby = parse_getarg(&state)))
00432 continue;
00433 rnl->markby = strdup(mby);
00434 } else if (strcmp(command, "access") == 0) {
00435 rnl = getRegNickData(parse_getarg(&state));
00436 addAccItem(rnl, parse_getarg(&state));
00437 } else if (!strcmp(command, "email")) {
00438 rnl = getRegNickData(parse_getarg(&state));
00439
00440 strncpyzt(rnl->email, parse_getarg(&state), EMAILLEN);
00441
00442 if (!strcmp(rnl->email, "(none)"))
00443 strcat(rnl->email, " ");
00444 } else if (!strcmp(command, "idtime")) {
00445 rnl = getRegNickData(parse_getarg(&state));
00446 rnl->idtime = atoi(parse_getarg(&state));
00447 } else if (!strcmp(command, "done"))
00448 done = 1;
00449 else {
00450 fprintf(stderr, NS_DB ":%d: Error reading nick data (%s)",
00451 line_num, dbLine);
00452 sshutdown(-1);
00453 }
00454 #ifdef DBDEBUG
00455 sSend(":%s PRIVMSG " DEBUGCHAN " :Read nick data (%s)", NICKSERV,
00456 dbLine);
00457 #endif
00458
00459 parse_cleanup(&state);
00460 }
00461 fclose(db.ns);
00462
00463 readMemoData();
00464 }
00465
00466
00467
00471 void saveChanUrls(RegChanList * first)
00472 {
00473 return;
00474 RegChanList *cl = first;
00475 const char *tmpFounderNick;
00476 FILE *fpOut;
00477 char cstr[258];
00478
00479 fpOut = fopen(CS_DIR "urls.txt.new", "w");
00480 if (!fpOut)
00481 return;
00482 while (cl) {
00483 if (!cl->name || !*cl->name || (cl->restrictlevel > 0)) {
00484 cl = cl->next;
00485 continue;
00486 }
00487 if (cl->mlock & (PM_S | PM_P | PM_I | PM_K)) {
00488 cl = cl->next;
00489 continue;
00490 }
00491
00492 tmpFounderNick = cl->founderId.getNick();
00493
00494 if (tmpFounderNick == NULL)
00495 tmpFounderNick = "-";
00496
00497 sprintf(cstr, ":%.255s",
00498 md5_printable(md5_password((u_char *)cl->password)));
00499 fprintf(fpOut, "C %s %s %ld %ld %s\n", cl->name,
00500 tmpFounderNick, cl->mlock, cl->flags,
00501 md5_printable(md5_password((u_char *)cstr)));
00502 memset(cstr, 0, 255);
00503 if (cl->topic)
00504 fprintf(fpOut, "topic %s %s %lu :%s\n", cl->name,
00505 *cl->tsetby ? cl->tsetby : "-", cl->ttimestamp,
00506 cl->topic);
00507 if (cl->url)
00508 fprintf(fpOut, "url %s :%s\n", cl->name, cl->url);
00509 fflush(fpOut);
00510 cl = cl->next;
00511 }
00512 if (fclose(fpOut) < 0) {
00513 sSend("GLOBOPS :Fatal error in writing out urls.txt.new.");
00514 return;
00515 }
00516 if (rename("chanserv/urls.txt.new", "chanserv/urls.txt") < 0) {
00517 sSend("GLOBOPS :Error renaming urls.txt.new.");
00518 return;
00519 }
00520 }
00521
00525 void saveChanData(RegChanList * first)
00526 {
00527 RegChanList *cl = first;
00528 cAccessList *accitem;
00529 cAkickList *akitem;
00530 const char *tmpFounderNick;
00531 int x = 0;
00532
00533 saveChanUrls(first);
00534 db.cs = NULL;
00535 db.cs = fopen(CS_DIR "chanserv.db", "w");
00536 if (db.cs == NULL) {
00537 sSend(":%s GOPER :ERROR: Unable to save Channel database fopen failed: %s", myname, strerror(errno));
00538 logDump(corelog, "Unable to save Channel database: fopen: %s", strerror(errno));
00539 return;
00540 }
00541
00542 fprintf(db.cs, "version 2\n");
00543
00544 while (cl) {
00545 tmpFounderNick = cl->founderId.getNick();
00546
00547 if (tmpFounderNick == NULL)
00548 tmpFounderNick = "-";
00549
00550
00551 fprintf(db.cs, "channel ");
00552 fprintf(db.cs, "%s %s ", cl->name, tmpFounderNick);
00553 fprintf(db.cs, "%lu %lu ", cl->mlock, cl->flags);
00554
00555 if (!(cl->flags & CENCRYPT)) {
00556 strcpy(cryptstr, (char *)cl->password);
00557 xorit(cryptstr);
00558 fprintf(db.cs, "@%s ", cryptstr);
00559 }
00560 else {
00561 u_char *tmpup = toBase64(cl->password, 16);
00562 if (!tmpup)
00563 abort();
00564 fprintf(db.cs, "$%s ", tmpup);
00565 FREE(tmpup);
00566 }
00567
00568 fprintf(db.cs, "%lu ", (unsigned long)cl->timereg);
00569 fprintf(db.cs, "%lu ", (unsigned long)cl->timestamp);
00570 fprintf(db.cs, "%s %lu %i ", cl->key, cl->limit, cl->memolevel);
00571 fprintf(db.cs, "%i %i :%s\n", cl->tlocklevel, cl->restrictlevel,
00572 cl->desc);
00573 if (cl->topic)
00574 fprintf(db.cs, "topic %s %s %lu :%s\n", cl->name, cl->tsetby,
00575 cl->ttimestamp, cl->topic);
00576 if (cl->url)
00577 fprintf(db.cs, "url %s :%s\n", cl->name, cl->url);
00578 if (cl->autogreet != NULL)
00579 fprintf(db.cs, "autogreet %s :%s\n", cl->name, cl->autogreet);
00580 if ((cl->flags & CMARK) && cl->markby)
00581 fprintf(db.cs, "markby %s %s\n", cl->name, cl->markby);
00582 if (cl->chpw_key)
00583 fprintf(db.cs, "chkey %X\n", cl->chpw_key);
00584 if (cl->firstOp) {
00585 const char *tmpName;
00586
00587 for (accitem = cl->firstOp; accitem; accitem = accitem->next) {
00588 tmpName = (accitem->nickId).getNick();
00589
00590 if (tmpName == NULL)
00591 continue;
00592 fprintf(db.cs, "op %s %s ", cl->name, tmpName);
00593 fprintf(db.cs, "%i\n", accitem->uflags);
00594 }
00595 }
00596
00597 if (cl->firstAkick) {
00598 for (akitem = cl->firstAkick; akitem; akitem = akitem->next) {
00599 fprintf(db.cs, "akick %s %s ", cl->name, akitem->mask);
00600 fprintf(db.cs, "%lu :%s\n", (u_long) akitem->added,
00601 akitem->reason);
00602 }
00603 }
00604 x++;
00605 fflush(db.cs);
00606 #ifdef DBDEBUG
00607 sSend(":%s PRIVMSG " DEBUGCHAN " :Saved chan data (%s)", ChanServ,
00608 cl->name);
00609 #endif
00610 cl = cl->next;
00611 }
00612 fprintf(db.cs, "done\n");
00613 fflush(db.cs);
00614 fclose(db.cs);
00615 #ifdef GLOBOPS_TIMED_MSGS
00616 sSend(":%s GLOBOPS :Completed save(%i)", ChanServ, x);
00617 #else
00618 sSend(":%s PRIVMSG " LOGCHAN " :Completed save(%i)", ChanServ, x);
00619 #endif
00620 }
00621
00625 void readChanData()
00626 {
00627 RegChanList *rcl;
00628 RegNickList *rnl;
00629 char *command;
00630 int done = 0, db_version = 1;
00631 int line_num = 0;
00632 char *pass;
00633 char *topic;
00634
00635 rcl = NULL;
00636 rnl = NULL;
00637 db.cs = fopen(CS_DIR "chanserv.db", "r");
00638 if (db.cs == NULL)
00639 return;
00640
00641 while (!done) {
00642 if ((sfgets(dbLine, 2048, db.cs)) == 0) {
00643 if (!done) {
00644 unexpected_eof(CS_DB);
00645 }
00646 done = 1;
00647 fclose(db.cs);
00648 return;
00649 }
00650 line_num++;
00651
00652 if (parse_init(&state, dbLine) != 0) {
00653 fprintf(stderr,
00654 CS_DIR "chanserv.db:%d: " " Fatal error during read "
00655 " (Null line?) \n", line_num);
00656 abort();
00657 }
00658
00659 command = parse_getarg(&state);
00660 if (!strcmp(command, "version")) {
00661 db_version = atoi(parse_getarg(&state));
00662 }
00663 else if (!strcmp(command, "channel")) {
00664 char *sChannelName, *sFounderNick;
00665
00666 rcl = (RegChanList *) oalloc(sizeof(RegChanList));
00667 sChannelName = parse_getarg(&state);
00668 sFounderNick = parse_getarg(&state);
00669 initRegChanData(rcl);
00670
00671 if (strlen(sChannelName) >= CHANLEN) {
00672 fprintf(stderr,
00673 CS_DIR "chanserv.db:%d: "
00674 " Channel name '%.80s' exceeds " " CHANLEN.\n",
00675 line_num, sChannelName);
00676 sshutdown(-1);
00677 } else if (strlen(sFounderNick) >= NICKLEN) {
00678 fprintf(stderr,
00679 CS_DIR "chanserv.db:%d: "
00680 " Founder nick name '%.80s' " " (%.80s)"
00681 " exceeds NICKLEN.\n", line_num, sFounderNick,
00682 sChannelName);
00683 sshutdown(-1);
00684 }
00685
00686 if (!sChannelName || !sFounderNick) {
00687 fprintf(stderr,
00688 CS_DIR "chanserv.db:%d: " " Parse error. (%p, %p)",
00689 line_num, sChannelName, sFounderNick);
00690 sshutdown(-1);
00691 }
00692
00693 rnl = getRegNickData(sFounderNick);
00694
00695 strcpy(rcl->name, sChannelName);
00696
00697 if (rnl)
00698 {
00699 rcl->founderId = rnl->regnum;
00700 rnl->chans++;
00701 }
00702 else
00703 rcl->founderId = RegId(0, 0);
00704
00705 rcl->mlock = atol(parse_getarg(&state));
00706 rcl->flags = atol(parse_getarg(&state));
00707 pass = parse_getarg(&state);
00708 if (!pass) {
00709 fprintf(stderr,
00710 CS_DIR "chanserv.db:%d: " " Null password?!",
00711 line_num);
00712 sshutdown(-1);
00713 }
00714
00715 if ((db_version < 2) || *pass == '@') {
00716 if (db_version < 2)
00717 strcpy((char *)rcl->password, pass);
00718 else
00719 strcpy((char *)rcl->password, pass + 1);
00720
00721 if (strlen(pass) > (u_int)((db_version < 2) ? PASSLEN : PASSLEN+1)) {
00722 fprintf(stderr,
00723 CS_DIR "chanserv.db:%d: " " password > PASSLEN",
00724 line_num);
00725 sshutdown(-1);
00726 }
00727
00728 xorit((char *)rcl->password);
00729 rcl->flags &= ~CENCRYPT;
00730 }
00731 else {
00732 u_char *tmpup = fromBase64(pass+1, NULL);
00733 int q;
00734
00735 if (!tmpup)
00736 abort();
00737 for(q = 0; q < 16; q++)
00738 rcl->password[q] = tmpup[q];
00739 FREE(tmpup);
00740 rcl->flags |= CENCRYPT;
00741 }
00742
00743 rcl->timereg = (time_t) atol(parse_getarg(&state));
00744 rcl->timestamp = (time_t) atol(parse_getarg(&state));
00745 strncpyzt(rcl->key, parse_getarg(&state), KEYLEN);
00746 rcl->limit = atol(parse_getarg(&state));
00747 rcl->memolevel = atoi(parse_getarg(&state));
00748 rcl->tlocklevel = atoi(parse_getarg(&state));
00749 rcl->restrictlevel = atoi(parse_getarg(&state));
00750
00751 topic = parse_getallargs(&state);
00752 if (topic == NULL)
00753 rcl->desc[0] = '\0';
00754 else
00755 strncpyzt(rcl->desc, topic, CHANDESCBUF);
00756 addRegChan(rcl);
00757 mostchans++;
00758 } else if (!strcmp(command, "topic")) {
00759 rcl = getRegChanData(parse_getarg(&state));
00760 if (rcl == NULL)
00761 continue;
00762 strncpyzt(rcl->tsetby, parse_getarg(&state), NICKLEN);
00763 rcl->ttimestamp = (time_t) atol(parse_getarg(&state));
00764
00765 topic = parse_getallargs(&state);
00766 if (topic == NULL)
00767 rcl->topic = NULL;
00768 else
00769 rcl->topic = strdup(topic);
00770 } else if (!strcmp(command, "url")) {
00771 rcl = getRegChanData(parse_getarg(&state));
00772 if (rcl == NULL)
00773 continue;
00774 topic = parse_getallargs(&state);
00775 if (topic == NULL)
00776 rcl->url = NULL;
00777 else
00778 rcl->url = strdup(topic);
00779 } else if (!strcmp(command, "autogreet")) {
00780 rcl = getRegChanData(parse_getarg(&state));
00781 if (rcl == NULL)
00782 continue;
00783 topic = parse_getallargs(&state);
00784 if (topic == NULL)
00785 rcl->autogreet = NULL;
00786 else
00787 rcl->autogreet = strdup(topic);
00788 } else if (!strcmp(command, "markby")) {
00789 rcl = getRegChanData(parse_getarg(&state));
00790 if (rcl == NULL)
00791 continue;
00792 topic = parse_getarg(&state);
00793 if (topic == NULL)
00794 rcl->markby = NULL;
00795 else
00796 rcl->markby = strdup(topic);
00797 } else if (strcmp(command, "chkey") == 0) {
00798 char *tmpp = parse_getarg(&state);
00799 if (rcl && tmpp)
00800 rcl->chpw_key = strtoul(tmpp, (char **)0, 16);
00801 } else if (!strcmp(command, "op")) {
00802 cAccessList *lame;
00803 char *tmpName;
00804
00805 rcl = getRegChanData(parse_getarg(&state));
00806 if (rcl == NULL)
00807 continue;
00808 tmpName = parse_getarg(&state);
00809 if ((rnl = getRegNickData(tmpName)) != NULL)
00810 {
00811 lame = (cAccessList *) oalloc(sizeof(cAccessList));
00812 lame->nickId = rnl->regnum;
00813 lame->uflags = atoi(parse_getarg(&state));
00814 addChanOp(rcl, lame);
00815 }
00816 } else if (!strcmp(command, "akick")) {
00817 cAkickList *lame;
00818 lame = (cAkickList *) oalloc(sizeof(cAkickList));
00819 rcl = getRegChanData(parse_getarg(&state));
00820 if (rcl == NULL)
00821 continue;
00822 strncpyzt(lame->mask, parse_getarg(&state), 70);
00823 lame->added = (time_t) atol(parse_getarg(&state));
00824
00825 topic = parse_getallargs(&state);
00826 if (topic == NULL)
00827 lame->reason[0] = '\0';
00828 else {
00829 strncpyzt(lame->reason, topic, NICKLEN + 50);
00830 }
00831 addChanAkick(rcl, lame);
00832 } else if (!strcmp(command, "done"))
00833 done = 1;
00834 else {
00835 fprintf(stderr, "GLOBOPS :Read chan data (%s)", dbLine);
00836 sshutdown(-1);
00837 }
00838
00839 #ifdef DBDEBUG
00840 sSend(":%s PRIVMSG " DEBGUGCHAN " :Read chan data (%s)", ChanServ,
00841 dbLine);
00842 #endif
00843
00844 parse_cleanup(&state);
00845 }
00846 fclose(db.cs);
00847 }
00848
00849
00853 void saveMemoData(void)
00854 {
00855 RegNickList *nl;
00856 MemoBox *tmp;
00857 MemoList *memo;
00858 MemoBlock *mbitem;
00859 const char *tmpNickName;
00860 int bucket;
00861 int totmemos;
00862 int totboxes;
00863
00864 db.ms = fopen(MS_DB, "w");
00865
00866 totmemos = 0;
00867 totboxes = 0;
00868
00869 for (bucket = 0; bucket < NICKHASHSIZE; bucket++) {
00870 nl = LIST_FIRST(&RegNickHash[bucket]);
00871
00872 while (nl != NULL) {
00873 tmp = nl->memos;
00874 if (tmp != NULL) {
00875 totboxes++;
00876 fprintf(db.ms, "data %s %i %i %i %i\n", nl->nick,
00877 tmp->memocnt, tmp->flags, tmp->flags, tmp->max);
00878 if (tmp->forward)
00879 fprintf(db.ms, "redirect %s %s\n", nl->nick,
00880 tmp->forward->nick);
00881 for (mbitem = tmp->firstMblock;
00882 mbitem;
00883 mbitem = mbitem->next
00884 )
00885 {
00886 if ((tmpNickName = mbitem->blockId.getNick()))
00887 fprintf(db.ms, "mblock %s\n", tmpNickName);
00888 }
00889
00890 for (memo = LIST_FIRST(&tmp->mb_memos); memo;
00891 memo = LIST_NEXT(memo, ml_lst)) {
00892 if (ShouldMemoExpire(memo, 0)) {
00893 memo = LIST_NEXT(memo, ml_lst);
00894 if (memo == NULL)
00895 break;
00896 continue;
00897 }
00898 fprintf(db.ms, "memo %s %i %i %lu %s %s :%s\n",
00899 nl->nick, 0, memo->flags, (long)memo->sent,
00900 memo->from, memo->to, memo->memotxt);
00901 totmemos++;
00902 }
00903 }
00904 nl = LIST_NEXT(nl, rn_lst);
00905 }
00906 }
00907
00908 fprintf(db.ms, "done\n");
00909
00910 fclose(db.ms);
00911
00912 sSend(":%s PRIVMSG " LOGCHAN " :Completed save(%u boxes, %u memos)",
00913 MemoServ, totboxes, totmemos);
00914 }
00915
00919 void readMemoData(void)
00920 {
00921 RegNickList *nick = NULL;
00922 RegNickList *from, *rnlb;
00923 MemoList *newmemo;
00924 char *command;
00925 char *topic;
00926 int done = 0;
00927 unsigned long linenum = 0;
00928
00929 db.ms = fopen(MS_DB, "r");
00930
00931 if (db.ms == NULL)
00932 return;
00933
00934 while (!done) {
00935 if (!(sfgets(dbLine, 2048, db.ms))) {
00936 if (!done) {
00937 unexpected_eof(MS_DB);
00938 }
00939 done = 1;
00940 fclose(db.ms);
00941 return;
00942 }
00943
00944 linenum++;
00945 if (parse_init(&state, dbLine) != 0) {
00947 abort();
00948 }
00949
00950 command = parse_getarg(&state);
00951
00952 if (strcmp(command, "data") == 0) {
00953 nick = getRegNickData(parse_getarg(&state));
00955 (void)parse_getarg(&state);
00956 (void)parse_getarg(&state);
00957 if (nick) {
00958 nick->memos->flags = atoi(parse_getarg(&state));
00959 nick->memos->max = atoi(parse_getarg(&state));
00960 if (nick->memos->max <= 0)
00961 nick->memos->max = MS_DEF_RCV_MAX;
00962 }
00963 } else if (strcmp(command, "mblock") == 0) {
00964 MemoBlock *mbitem;
00965 if (nick && nick->memos) {
00966 char *nickToBlock;
00967
00968 if ((nickToBlock = parse_getarg(&state))
00969 && (rnlb = getRegNickData(nickToBlock))) {
00970
00971 mbitem = (MemoBlock *) oalloc(sizeof(MemoBlock));
00972 mbitem->blockId = rnlb->regnum;
00973 mbitem->next = nick->memos->firstMblock;
00974 nick->memos->firstMblock = mbitem;
00975 }
00976 }
00977 } else if (strcmp(command, "redirect") == 0) {
00978 nick = getRegNickData(parse_getarg(&state));
00979 if (nick != NULL)
00980 nick->memos->forward =
00981 getRegNickData(parse_getarg(&state));
00982 } else if (strcmp(command, "memo") == 0) {
00983 char *cn;
00984
00985 cn = parse_getarg(&state);
00986
00987 nick = getRegNickData(cn);
00988 if (nick == NULL) {
00989 printf("memo: %s not valid\n", cn);
00990 continue;
00991 }
00992 newmemo = (MemoList *) oalloc(sizeof(MemoList));
00993 newmemo->realto = nick;
00995 (void)parse_getarg(&state);
00996 newmemo->flags = atoi(parse_getarg(&state));
00997 newmemo->sent = (time_t) atol(parse_getarg(&state));
00998
00999
01000
01001 if ((time(NULL) - newmemo->sent) >= NICKDROPTIME) {
01002 FREE(newmemo);
01003 continue;
01004 }
01005
01006 strncpyzt(newmemo->from, parse_getarg(&state), NICKLEN);
01007 from = getRegNickData(newmemo->from);
01008 strncpyzt(newmemo->to, parse_getarg(&state), CHANLEN);
01009
01010
01011 topic = parse_getallargs(&state);
01012 if (topic == NULL) {
01013 FREE(newmemo);
01014 continue;
01015 }
01016 newmemo->memotxt = strdup(topic);
01017
01018
01019 LIST_ENTRY_INIT(newmemo, ml_lst);
01020 LIST_INSERT_HEAD(&nick->memos->mb_memos, newmemo, ml_lst);
01021 if (from && newmemo->flags & MEMO_UNREAD)
01022 LIST_INSERT_HEAD(&from->memos->mb_sent, newmemo, ml_sent);
01023 nick->memos->memocnt++;
01024 } else if (strcmp(command, "done") == 0) {
01025 done = 1;
01026 } else {
01027 fprintf(stderr, "Error in reading memo data (%s) %lu\n",
01028 dbLine, linenum);
01029 sshutdown(-1);
01030 }
01031 #ifdef DBDEBUG
01032 sSend(":%s PRIVMSG " DEBUGCHAN " :Read memo data (%s)", MemoServ,
01033 dbLine);
01034 #endif
01035
01036 parse_cleanup(&state);
01037 }
01038
01039 fclose(db.ms);
01040 }
01041
01042
01046 void saveTriggerData(void)
01047 {
01048 int totrules = 0;
01049 CloneRule *rule;
01050 extern CloneRule *first_crule;
01051
01052 db.trigger = fopen(TRG_DB, "w");
01053 if (!db.trigger) {
01054 logDump(corelog,
01055 "Unable to open trigger database for read access: %s",
01056 strerror(errno));
01057 sSend
01058 (":%s GLOBOPS :Unable to open trigger database for read access: %s",
01059 NickServ, strerror(errno));
01060 return;
01061 }
01062 for (rule = first_crule; rule; rule = rule->next, ++totrules) {
01063 if (fprintf
01064 (db.trigger, "Trigger %s %d %d %ld\n", rule->mask,
01065 rule->trigger, rule->utrigger, rule->flags) < 0) {
01066 logDump(corelog,
01067 "Error in writing rule to trigger database: %s",
01068 strerror(errno));
01069 break;
01070 }
01071 if (rule->kill_msg) {
01072 if ((fprintf(db.trigger, "Killmsg %s\n", rule->kill_msg)) < 0) {
01073 logDump(corelog,
01074 "Error in writing trigger rule (killmsg) to trigger database: %s",
01075 strerror(errno));
01076 break;
01077 }
01078 }
01079 if (rule->warn_msg) {
01080 if ((fprintf(db.trigger, "Warnmsg %s\n", rule->warn_msg)) < 0) {
01081 logDump(corelog,
01082 "Error in writing trigger rule (warnlmsg) to trigger database: %s",
01083 strerror(errno));
01084 break;
01085 }
01086 }
01087 }
01088 fprintf(db.trigger, "done\n");
01089
01090 if (fclose(db.trigger) < 0) {
01091 logDump(corelog, "Error closing trigger database: %s",
01092 strerror(errno));
01093 return;
01094 }
01095 sSend(":%s PRIVMSG " LOGCHAN " :Completed trigger save (%u rules)",
01096 OperServ, totrules);
01097 }
01098
01102 void readTriggerData(void)
01103 {
01104 CloneRule *rule = NULL;
01105 char *command, *text;
01106 int done = 0;
01107 unsigned long linenum = 0;
01108
01109 db.trigger = fopen(TRG_DB, "r");
01110
01111 if (db.trigger == NULL) {
01112 logDump(corelog,
01113 "Unable to open trigger database for read access: %s",
01114 strerror(errno));
01115 return;
01116 }
01117
01118 while (!done) {
01119 if (!(sfgets(dbLine, 2048, db.trigger))) {
01120 if (!done) {
01121 unexpected_eof(TRG_DB);
01122 }
01123 done = 1;
01124 fclose(db.trigger);
01125 return;
01126 }
01127 linenum++;
01128
01129 if (parse_init(&state, dbLine) != 0) {
01131 abort();
01132 }
01133
01134 command = parse_getarg(&state);
01135
01136 if (strcmp(command, "Trigger") == 0) {
01137 rule = NewCrule();
01138 rule->kill_msg = NULL;
01139 rule->warn_msg = NULL;
01140 strncpyzt(rule->mask, parse_getarg(&state),
01141 sizeof(rule->mask));
01142 rule->mask[sizeof(rule->mask) - 1] = '\0';
01143 rule->trigger = atoi(parse_getarg(&state));
01144 rule->utrigger = atoi(parse_getarg(&state));
01145 rule->flags = atol(parse_getarg(&state));
01146 AddCrule(rule, -2);
01147 } else if (strcmp(command, "Killmsg") == 0) {
01148 text = parse_getallargs(&state);
01149 if (text && rule)
01150 rule->kill_msg = strdup(text);
01151 } else if (strcmp(command, "Warnmsg") == 0) {
01152 text = parse_getallargs(&state);
01153 if (text && rule)
01154 rule->warn_msg = strdup(text);
01155 } else if (strcmp(command, "done") == 0) {
01156 done = 1;
01157 } else {
01158 fprintf(stderr, "Error in reading trigger data (%s) %lu\n",
01159 dbLine, linenum);
01160 parse_cleanup(&state);
01161 return;
01162 }
01163 #ifdef DBDEBUG
01164 sSend(":%s PRIVMSG " DEBUGCHAN " :Read trigger data (%s)",
01165 OperServ, dbLine);
01166 #endif
01167
01168 parse_cleanup(&state);
01169 }
01170
01171 fclose(db.trigger);
01172 }
01173
01177 void saveInfoData(void)
01178 {
01179 SomeNews *news = NULL;
01180 int index = 0;
01181
01182 db.is = fopen(IS_DB, "w");
01183
01184 if (db.is == NULL) {
01185 sSend(":%s GOPER :ERROR: Unable to save Info Article database fopen failed: %s", myname, strerror(errno));
01186 logDump(corelog, "Unable to save Info Article database: fopen: %s", strerror(errno));
01187 return;
01188 }
01189
01191 if (is_listhead != NULL) {
01192 for (news = is_listhead, index = 0; news;
01193 news = news->next, index++)
01194 {
01195 fprintf(db.is, "article %i %s %li %s\n", news->importance,
01196 news->from, news->timestamp, news->header);
01197 dbWriteString(db.is, news->content);
01198 }
01199 }
01200
01201 fprintf(db.is, "done\n");
01202
01203 fclose(db.is);
01204
01205 sSend(":%s PRIVMSG " LOGCHAN " :Completed save(%i articles)", InfoServ,
01206 index);
01207 }
01208
01209
01213 void readInfoData(void)
01214 {
01215 char *command;
01216 int done = 0;
01217 SomeNews *news, *tmpnews;
01218
01219 is_listhead = NULL;
01220 db.is = fopen(IS_DB, "r");
01221
01222 if (db.is == NULL)
01223 return;
01224
01234 while (!done) {
01235 if (!(sfgets(dbLine, 2048, db.is))) {
01236 if (!done) {
01237 unexpected_eof(IS_DB);
01238 }
01239 done = 1;
01240 fclose(db.is);
01241 return;
01242 }
01243
01244 if (parse_init(&state, dbLine) != 0) {
01246 abort();
01247 }
01248
01249 command = parse_getarg(&state);
01250
01251 if (!strcmp(command, "article")) {
01252 char *temp;
01253
01254 news = (SomeNews *) oalloc(sizeof(SomeNews));
01255 if (!is_listhead)
01256 is_listhead = news;
01257 else {
01258 for (tmpnews = is_listhead; tmpnews->next;
01259 tmpnews = tmpnews->next);
01260 tmpnews->next = news;
01261 }
01262 news->importance = atoi(parse_getarg(&state));
01263 strncpyzt(news->from, parse_getarg(&state), NICKLEN);
01264 news->timestamp = atol(parse_getarg(&state));
01265 temp = parse_getallargs(&state);
01266 if (temp)
01267 news->header = strdup(temp);
01268 news->content = dbReadString(db.is);
01269
01270 if (news->timestamp > is_last_post_time)
01271 is_last_post_time = news->timestamp;
01272 }
01273
01274 else if (!strcmp(command, "done"))
01275 done = 1;
01276 else
01277 sshutdown(-1);
01278
01279 parse_cleanup(&state);
01280 }
01281 fclose(db.is);
01282 }
01283
01287 void sync_cfg(char *type)
01288 {
01289 void writeServicesTotals();
01290
01291 switch (*type) {
01292 case '1':
01293 syncNickData((time_t) (CTime + (SYNCTIME * 3)));
01294 writeServicesTotals();
01295 nextCsync = (CTime + SYNCTIME);
01296 nextMsync = (CTime + (SYNCTIME * 2));
01297 nextNsync = (CTime + (SYNCTIME * 3));
01298 timer(SYNCTIME, sync_cfg, (void *)(const_cast<char *>("2")));
01299 break;
01300 case '2':
01301 syncChanData((time_t) (CTime + (SYNCTIME * 2)));
01302 writeServicesTotals();
01303 nextMsync = (CTime + SYNCTIME);
01304 nextNsync = (CTime + (SYNCTIME * 2));
01305 nextCsync = (CTime + (SYNCTIME * 2));
01306
01307 timer(SYNCTIME, sync_cfg, (void *)const_cast<char *>("3"));
01308 break;
01309 case '3':
01310 syncMemoData((time_t) (CTime + SYNCTIME));
01311 nextNsync = nextCsync = nextMsync = (CTime + SYNCTIME);
01312 timer(SYNCTIME, sync_cfg, (void *)const_cast<char *>("4"));
01313 break;
01314 case '4':
01315 syncNickData((time_t) (CTime + SYNCTIME));
01316 syncChanData((time_t) (CTime + (SYNCTIME * 2)));
01317 syncMemoData((time_t) (CTime + (SYNCTIME * 3)));
01318 nextNsync = (CTime + SYNCTIME);
01319 nextCsync = (CTime + SYNCTIME * 2);
01320 nextMsync = (CTime + SYNCTIME * 3);
01321 timer(SYNCTIME, sync_cfg, (void *)const_cast<char *>("1"));
01322 break;
01323 }
01324 }
01325
01326 #ifdef REQ_EMAIL
01327 void saveRegData(nRegList *first) {
01328 nRegList *nl = first;
01329 db.nsreg = fopen("nickserv/nickregs.db", "w");
01330 while(nl) {
01331 fprintf(db.nsreg, "-\n%s\n%i\n", nl->email, nl->regs);
01332 nl=nl->next;
01333 fflush(db.nsreg);
01334 }
01335 fclose(db.nsreg);
01336 }
01337
01338 void readRegData(void) {
01339 char tmp2[10 + HOSTLEN], tmp[10];
01340 int lineread = 1, i;
01341 db.nsreg = fopen("nickserv/nickregs.db", "r");
01342 if(!db.nsreg)
01343 return;
01344 while(sfgets(tmp, 10, db.nsreg)) {
01345 if(tmp[0] != '-') {
01346 sSend("GOPER :!ERROR! NickServ databases are corrupted (line %i)", lineread);
01347 sshutdown(1);
01348 }
01349 sfgets(tmp2, 10 + HOSTLEN, db.nsreg);
01350 addNReg(tmp2);
01351 sfgets(tmp, 10, db.nsreg);
01352 i = atoi(tmp);
01353 for(i--;i;i--)
01354 addNReg(tmp2);
01355 }
01356 fclose(db.nsreg);
01357 }
01358 #endif