nickserv.c

Go to the documentation of this file.
00001 
00002 /* NickServ functions.
00003  *
00004  * (C) 2003-2007 Anope Team
00005  * Contact us at info@anope.org
00006  *
00007  * Please read COPYING and README for further details.
00008  *
00009  * Based on the original code of Epona by Lara.
00010  * Based on the original code of Services by Andy Church. 
00011  * 
00012  * $Id: nickserv.c 1265 2007-08-26 15:33:06Z geniusdex $
00013  *
00014  */
00015 
00016 #include "services.h"
00017 #include "pseudo.h"
00018 
00019 /*************************************************************************/
00020 
00021 #define HASH(nick)  ((tolower((nick)[0])&31)<<5 | (tolower((nick)[1])&31))
00022 
00023 NickAlias *nalists[1024];
00024 NickCore *nclists[1024];
00025 NickRequest *nrlists[1024];
00026 
00027 unsigned int guestnum;          /* Current guest number */
00028 
00029 #define TO_COLLIDE   0          /* Collide the user with this nick */
00030 #define TO_RELEASE   1          /* Release a collided nick */
00031 
00032 /*************************************************************************/
00033 
00034 static void add_ns_timeout(NickAlias * na, int type, time_t delay);
00035 
00036 /*************************************************************************/
00037 /* *INDENT-OFF* */
00038 void moduleAddNickServCmds(void) {
00039     modules_core_init(NickServCoreNumber, NickServCoreModules);
00040 }
00041 /* *INDENT-ON* */
00042 /*************************************************************************/
00043 
00044 /* Display total number of registered nicks and info about each; or, if
00045  * a specific nick is given, display information about that nick (like
00046  * /msg NickServ INFO <nick>).  If count_only != 0, then only display the
00047  * number of registered nicks (the nick parameter is ignored).
00048  */
00049 
00050 void listnicks(int count_only, const char *nick)
00051 {
00052     int count = 0;
00053     NickAlias *na;
00054     int i;
00055     char *end;
00056 
00057     if (count_only) {
00058 
00059         for (i = 0; i < 1024; i++) {
00060             for (na = nalists[i]; na; na = na->next)
00061                 count++;
00062         }
00063         printf("%d nicknames registered.\n", count);
00064 
00065     } else if (nick) {
00066 
00067         struct tm *tm;
00068         char buf[512];
00069         static const char commastr[] = ", ";
00070         int need_comma = 0;
00071 
00072         if (!(na = findnick(nick))) {
00073             printf("%s not registered.\n", nick);
00074             return;
00075         } else if (na->status & NS_VERBOTEN) {
00076             printf("%s is FORBIDden.\n", nick);
00077             return;
00078         }
00079         printf("%s is %s\n", nick, na->last_realname);
00080         printf("Last seen address: %s\n", na->last_usermask);
00081         tm = localtime(&na->time_registered);
00082         strftime(buf, sizeof(buf),
00083                  getstring(NULL, STRFTIME_DATE_TIME_FORMAT), tm);
00084         printf("  Time registered: %s\n", buf);
00085         tm = localtime(&na->last_seen);
00086         strftime(buf, sizeof(buf),
00087                  getstring(NULL, STRFTIME_DATE_TIME_FORMAT), tm);
00088         printf("   Last seen time: %s\n", buf);
00089         if (na->nc->url)
00090             printf("              URL: %s\n", na->nc->url);
00091         if (na->nc->email)
00092             printf("   E-mail address: %s\n", na->nc->email);
00093         if (na->nc->icq)
00094             printf("            ICQ #: %d\n", na->nc->icq);
00095         if (na->nc->greet)
00096             printf("            Greet: %s\n", na->nc->greet);
00097         *buf = 0;
00098         end = buf;
00099         if (na->nc->flags & NI_KILLPROTECT) {
00100             end +=
00101                 snprintf(end, sizeof(buf) - (end - buf),
00102                          "Kill protection");
00103             need_comma = 1;
00104         }
00105         if (na->nc->flags & NI_SECURE) {
00106             end += snprintf(end, sizeof(buf) - (end - buf), "%sSecurity",
00107                             need_comma ? commastr : "");
00108             need_comma = 1;
00109         }
00110         if (na->nc->flags & NI_PRIVATE) {
00111             end += snprintf(end, sizeof(buf) - (end - buf), "%sPrivate",
00112                             need_comma ? commastr : "");
00113             need_comma = 1;
00114         }
00115         if (na->status & NS_NO_EXPIRE) {
00116             end += snprintf(end, sizeof(buf) - (end - buf), "%sNo Expire",
00117                             need_comma ? commastr : "");
00118             need_comma = 1;
00119         }
00120         printf("          Options: %s\n", *buf ? buf : "None");
00121 
00122     } else {
00123 
00124         for (i = 0; i < 1024; i++) {
00125             for (na = nalists[i]; na; na = na->next) {
00126                 printf("    %s %-20s  %s\n",
00127                        na->status & NS_NO_EXPIRE ? "!" : " ",
00128                        na->nick, na->status & NS_VERBOTEN ?
00129                        "Disallowed (FORBID)" : na->last_usermask);
00130                 count++;
00131             }
00132         }
00133         printf("%d nicknames registered.\n", count);
00134 
00135     }
00136 }
00137 
00138 /*************************************************************************/
00139 
00140 /* Return information on memory use.  Assumes pointers are valid. */
00141 
00142 void get_aliases_stats(long *nrec, long *memuse)
00143 {
00144     long count = 0, mem = 0;
00145     int i;
00146     NickAlias *na;
00147 
00148     for (i = 0; i < 1024; i++) {
00149         for (na = nalists[i]; na; na = na->next) {
00150             count++;
00151             mem += sizeof(*na);
00152             if (na->nick)
00153                 mem += strlen(na->nick) + 1;
00154             if (na->last_usermask)
00155                 mem += strlen(na->last_usermask) + 1;
00156             if (na->last_realname)
00157                 mem += strlen(na->last_realname) + 1;
00158             if (na->last_quit)
00159                 mem += strlen(na->last_quit) + 1;
00160         }
00161     }
00162     *nrec = count;
00163     *memuse = mem;
00164 }
00165 
00166 /*************************************************************************/
00167 
00168 /* Return information on memory use.  Assumes pointers are valid. */
00169 
00170 void get_core_stats(long *nrec, long *memuse)
00171 {
00172     long count = 0, mem = 0;
00173     int i, j;
00174     NickCore *nc;
00175     char **accptr;
00176 
00177     for (i = 0; i < 1024; i++) {
00178         for (nc = nclists[i]; nc; nc = nc->next) {
00179             count++;
00180             mem += sizeof(*nc);
00181 
00182             if (nc->display)
00183                 mem += strlen(nc->display) + 1;
00184             if (nc->pass)
00185                 mem += strlen(nc->pass) + 1;
00186 
00187             if (nc->url)
00188                 mem += strlen(nc->url) + 1;
00189             if (nc->email)
00190                 mem += strlen(nc->email) + 1;
00191             if (nc->greet)
00192                 mem += strlen(nc->greet) + 1;
00193 
00194             mem += sizeof(char *) * nc->accesscount;
00195             for (accptr = nc->access, j = 0; j < nc->accesscount;
00196                  accptr++, j++) {
00197                 if (*accptr)
00198                     mem += strlen(*accptr) + 1;
00199             }
00200 
00201             mem += nc->memos.memocount * sizeof(Memo);
00202             for (j = 0; j < nc->memos.memocount; j++) {
00203                 if (nc->memos.memos[j].text)
00204                     mem += strlen(nc->memos.memos[j].text) + 1;
00205             }
00206 
00207             mem += sizeof(void *) * nc->aliases.count;
00208         }
00209     }
00210     *nrec = count;
00211     *memuse = mem;
00212 }
00213 
00214 /*************************************************************************/
00215 /*************************************************************************/
00216 
00217 /* NickServ initialization. */
00218 
00219 void ns_init(void)
00220 {
00221     moduleAddNickServCmds();
00222     guestnum = time(NULL);
00223     while (guestnum > 9999999)
00224         guestnum -= 10000000;
00225 }
00226 
00227 /*************************************************************************/
00228 
00229 /* Main NickServ routine. */
00230 
00231 void nickserv(User * u, char *buf)
00232 {
00233     char *cmd, *s;
00234 
00235     cmd = strtok(buf, " ");
00236 
00237     if (!cmd) {
00238         return;
00239     } else if (stricmp(cmd, "\1PING") == 0) {
00240         if (!(s = strtok(NULL, ""))) {
00241             s = "";
00242         }
00243         anope_cmd_ctcp(s_NickServ, u->nick, "PING %s", s);
00244     } else if (skeleton) {
00245         notice_lang(s_NickServ, u, SERVICE_OFFLINE, s_NickServ);
00246     } else {
00247         mod_run_cmd(s_NickServ, u, NICKSERV, cmd);
00248     }
00249 
00250 }
00251 
00252 /*************************************************************************/
00253 
00254 /* Load/save data files. */
00255 
00256 
00257 #define SAFE(x) do {                    \
00258     if ((x) < 0) {                  \
00259     if (!forceload)                 \
00260         fatal("Read error on %s", NickDBName);  \
00261     failed = 1;                 \
00262     break;                      \
00263     }                           \
00264 } while (0)
00265 
00266 /* Loads NickServ database versions 5 to 11 (<= 4 is not supported) */
00267 
00268 void load_old_ns_dbase(void)
00269 {
00270     dbFILE *f;
00271     int ver, i, j, c;
00272     NickAlias *na, *na2, *next;
00273     NickCore *nc;
00274     int failed = 0;
00275 
00276     uint16 tmp16;
00277     uint32 tmp32;
00278 
00279     char bufn[NICKMAX], bufp[PASSMAX];
00280     char *email, *greet, *url, *forbidby, *forbidreason;
00281     uint32 icq;
00282 
00283     if (!(f = open_db(s_NickServ, NickDBName, "r", NICK_VERSION)))
00284         return;
00285 
00286     ver = get_file_version(f);
00287     if (ver <= 4) {
00288         fatal("Unsupported version number (%d) on %s", ver, NickDBName);
00289         close_db(f);
00290         return;
00291     }
00292 
00293     for (i = 0; i < 256 && !failed; i++) {
00294         while ((c = getc_db(f)) == 1) {
00295             if (c != 1)
00296                 fatal("Invalid format in %s", NickDBName);
00297 
00298             na = scalloc(sizeof(NickAlias), 1);
00299 
00300             SAFE(read_buffer(bufn, f));
00301             na->nick = sstrdup(bufn);
00302             SAFE(read_buffer(bufp, f)); /* Will be used later if needed */
00303 
00304             SAFE(read_string(&url, f));
00305             SAFE(read_string(&email, f));
00306             if (ver >= 10)
00307                 SAFE(read_int32(&icq, f));
00308             else
00309                 icq = 0;
00310             if (ver >= 9)
00311                 SAFE(read_string(&greet, f));
00312             else
00313                 greet = NULL;
00314 
00315             SAFE(read_string(&na->last_usermask, f));
00316             SAFE(read_string(&na->last_realname, f));
00317             SAFE(read_string(&na->last_quit, f));
00318 
00319             SAFE(read_int32(&tmp32, f));
00320             na->time_registered = tmp32;
00321             SAFE(read_int32(&tmp32, f));
00322             na->last_seen = tmp32;
00323 
00324             SAFE(read_int16(&na->status, f));
00325             na->status &= ~NS_TEMPORARY;
00326 
00327             if (ver >= 9) {
00328                 SAFE(read_string(&forbidby, f));
00329                 SAFE(read_string(&forbidreason, f));
00330                 /* Cleanup */
00331                 if (forbidby && *forbidby == '@') {
00332                     free(forbidby);
00333                     forbidby = NULL;
00334                 }
00335                 if (forbidreason && *forbidreason == 0) {
00336                     free(forbidreason);
00337                     forbidreason = NULL;
00338                 }
00339             } else {
00340                 forbidby = NULL;
00341                 forbidreason = NULL;
00342             }
00343 
00344             if (na->status & NS_VERBOTEN) {
00345                 if (na->last_usermask)
00346                     free(na->last_usermask);
00347                 if (na->last_realname)
00348                     free(na->last_realname);
00349 
00350                 na->last_usermask = forbidby;
00351                 na->last_realname = forbidreason;
00352             } else {
00353                 if (!na->last_usermask)
00354                     na->last_usermask = sstrdup("");
00355                 if (!na->last_realname)
00356                     na->last_realname = sstrdup("");
00357             }
00358 
00359             /* Store the reference for later resolving */
00360             SAFE(read_string((char **) &na->nc, f));
00361             SAFE(read_int16(&tmp16, f));        /* Was linkcount */
00362 
00363             if (na->nc) {
00364                 SAFE(read_int16(&tmp16, f));    /* Was channelcount */
00365             } else {
00366                 /* This nick was a master nick, so it also has all the
00367                  * core info! =)
00368                  */
00369                 nc = scalloc(1, sizeof(NickCore));
00370                 slist_init(&nc->aliases);
00371 
00372                 /* The initial display is what used to be the master nick */
00373                 nc->display = sstrdup(na->nick);
00374 
00375                 /* We grabbed info before; fill the appropriate fields now */
00376                 if (*bufp)
00377                     nc->pass = sstrdup(bufp);
00378                 else
00379                     nc->pass = NULL;    /* Which may be the case for forbidden nicks .. */
00380 
00381                 nc->email = email;
00382                 nc->greet = greet;
00383                 nc->icq = icq;
00384                 nc->url = url;
00385 
00386                 /* We check whether the e-mail is valid because it was not tested
00387                  * in older versions.
00388                  */
00389                 if (ver <= 10 && nc->email && !MailValidate(nc->email)) {
00390                     free(nc->email);
00391                     nc->email = NULL;
00392                 }
00393 
00394                 SAFE(read_int32(&nc->flags, f));
00395                 if (!NSAllowKillImmed)
00396                     nc->flags &= ~NI_KILL_IMMED;
00397 
00398                 /* Status flags cleanup */
00399                 if (na->status & NS_OLD_ENCRYPTEDPW) {
00400                     nc->flags |= NI_ENCRYPTEDPW;
00401                     na->status &= ~NS_OLD_ENCRYPTEDPW;
00402                 }
00403 
00404                 /* Add services opers and admins to the appropriate list, but
00405                    only if the database version is equal to or more than 10. */
00406                 if (ver >= 10) {
00407                     if (nc->flags & NI_SERVICES_ADMIN)
00408                         slist_add(&servadmins, nc);
00409                     if (nc->flags & NI_SERVICES_OPER)
00410                         slist_add(&servopers, nc);
00411                 }
00412 
00413                 /* Add the Services root flag if needed. */
00414                 if (nc)
00415                     for (j = 0; j < RootNumber; j++)
00416                         if (!stricmp(ServicesRoots[j], na->nick))
00417                             nc->flags |= NI_SERVICES_ROOT;
00418 
00419                 SAFE(read_int16(&nc->accesscount, f));
00420                 if (nc->accesscount) {
00421                     char **access;
00422                     access = scalloc(sizeof(char *) * nc->accesscount, 1);
00423                     nc->access = access;
00424                     for (j = 0; j < nc->accesscount; j++, access++)
00425                         SAFE(read_string(access, f));
00426                 }
00427 
00428                 SAFE(read_int16(&tmp16, f));
00429                 nc->memos.memocount = (int16) tmp16;
00430                 SAFE(read_int16(&tmp16, f));
00431                 nc->memos.memomax = (int16) tmp16;
00432                 if (nc->memos.memocount) {
00433                     Memo *memos;
00434                     memos = scalloc(sizeof(Memo) * nc->memos.memocount, 1);
00435                     nc->memos.memos = memos;
00436 
00437                     for (j = 0; j < nc->memos.memocount; j++, memos++) {
00438                         SAFE(read_int32(&memos->number, f));
00439                         SAFE(read_int16(&memos->flags, f));
00440                         SAFE(read_int32(&tmp32, f));
00441                         memos->time = tmp32;
00442                         SAFE(read_buffer(memos->sender, f));
00443                         SAFE(read_string(&memos->text, f));
00444                         memos->moduleData = NULL;
00445                     }
00446                 }
00447 
00448                 /* We read the channel count, but don't take care of it.
00449                    load_cs_dbase will regenerate it correctly. */
00450                 SAFE(read_int16(&tmp16, f));
00451                 SAFE(read_int16(&nc->channelmax, f));
00452                 if (ver == 5)
00453                     nc->channelmax = CSMaxReg;
00454 
00455                 SAFE(read_int16(&nc->language, f));
00456 
00457                 if (ver >= 11 && ver < 13) {
00458                     char *s;
00459 
00460                     SAFE(read_int16(&tmp16, f));
00461                     SAFE(read_int32(&tmp32, f));
00462                     SAFE(read_int16(&tmp16, f));
00463                     SAFE(read_string(&s, f));
00464                 }
00465 
00466                 /* Set us as being a master nick; fill the nc field also.
00467                    The NS_MASTER flag will not be cleared in this function. */
00468                 na->status |= NS_MASTER;
00469                 na->nc = nc;
00470                 slist_add(&nc->aliases, na);
00471 
00472                 /* Insert our new core in the core list */
00473                 insert_core(nc);
00474             }
00475 
00476             alpha_insert_alias(na);
00477 
00478         }                       /* while (getc_db(f) != 0) */
00479     }                           /* for (i) */
00480 
00481     /* Now resolve what were called links */
00482     for (i = 0; i < 1024; i++) {
00483         for (na = nalists[i]; na; na = next) {
00484             next = na->next;
00485 
00486             /* Master nicks are already resolved */
00487             if (na->status & NS_MASTER)
00488                 continue;
00489 
00490             na2 = na;
00491             /* While the reference resolves and it's not a master nick */
00492             while ((na2 = findnick((char *) na2->nc))
00493                    && !(na2->status & NS_MASTER));
00494 
00495             /* It didn't resolve. This is problematic since there is no core. :/
00496                We delete the nick. */
00497             if (!na2) {
00498                 alog("%s: while loading database: %s was linked to inexistant %s", s_NickServ, na->nick, (char *) na->nc);
00499                 delnick(na);
00500                 continue;
00501             }
00502 
00503             /* OK we have information on the core. We mark the current alias
00504                as a master nick because it now contains a valid core. */
00505             na->nc = na2->nc;
00506             na->status |= NS_MASTER;
00507             slist_add(&na->nc->aliases, na);
00508         }
00509     }
00510 
00511     close_db(f);
00512 }
00513 
00514 void load_ns_req_db(void)
00515 {
00516     dbFILE *f;
00517     int i, c, ver;
00518     NickRequest *nr;
00519     uint32 tmp32;
00520     int failed = 0;
00521 
00522     if (!(f = open_db(s_NickServ, PreNickDBName, "r", PRE_NICK_VERSION)))
00523         return;
00524     ver = get_file_version(f);
00525     for (i = 0; i < 1024 && !failed; i++) {
00526         while ((c = getc_db(f)) == 1) {
00527             if (c != 1)
00528                 fatal("Invalid format in %s", PreNickDBName);
00529             nr = scalloc(1, sizeof(NickRequest));
00530             SAFE(read_string(&nr->nick, f));
00531             SAFE(read_string(&nr->passcode, f));
00532             SAFE(read_string(&nr->password, f));
00533             SAFE(read_string(&nr->email, f));
00534             SAFE(read_int32(&tmp32, f));
00535             nr->requested = tmp32;
00536             insert_requestnick(nr);
00537         }
00538     }
00539     close_db(f);
00540 }
00541 
00542 void load_ns_dbase(void)
00543 {
00544     dbFILE *f;
00545     int ver, i, j, c;
00546     NickAlias *na, **nalast, *naprev;
00547     NickCore *nc, **nclast, *ncprev;
00548     int failed = 0;
00549     uint16 tmp16;
00550     uint32 tmp32;
00551     char *s;
00552 
00553     if (!(f = open_db(s_NickServ, NickDBName, "r", NICK_VERSION)))
00554         return;
00555 
00556     ver = get_file_version(f);
00557 
00558     if (ver <= 11) {
00559         close_db(f);
00560         load_old_ns_dbase();
00561         return;
00562     }
00563 
00564     /* First we load nick cores */
00565     for (i = 0; i < 1024 && !failed; i++) {
00566         nclast = &nclists[i];
00567         ncprev = NULL;
00568 
00569         while ((c = getc_db(f)) == 1) {
00570             if (c != 1)
00571                 fatal("Invalid format in %s", NickDBName);
00572 
00573             nc = scalloc(1, sizeof(NickCore));
00574             *nclast = nc;
00575             nclast = &nc->next;
00576             nc->prev = ncprev;
00577             ncprev = nc;
00578 
00579             slist_init(&nc->aliases);
00580 
00581             SAFE(read_string(&nc->display, f));
00582             SAFE(read_string(&nc->pass, f));
00583             SAFE(read_string(&nc->email, f));
00584             SAFE(read_string(&nc->greet, f));
00585             SAFE(read_int32(&nc->icq, f));
00586             SAFE(read_string(&nc->url, f));
00587 
00588             SAFE(read_int32(&nc->flags, f));
00589             if (!NSAllowKillImmed)
00590                 nc->flags &= ~NI_KILL_IMMED;
00591             SAFE(read_int16(&nc->language, f));
00592 
00593             /* Add services opers and admins to the appropriate list, but
00594                only if the database version is more than 10. */
00595             if (nc->flags & NI_SERVICES_ADMIN)
00596                 slist_add(&servadmins, nc);
00597             if (nc->flags & NI_SERVICES_OPER)
00598                 slist_add(&servopers, nc);
00599 
00600             SAFE(read_int16(&nc->accesscount, f));
00601             if (nc->accesscount) {
00602                 char **access;
00603                 access = scalloc(sizeof(char *) * nc->accesscount, 1);
00604                 nc->access = access;
00605                 for (j = 0; j < nc->accesscount; j++, access++)
00606                     SAFE(read_string(access, f));
00607             }
00608 
00609             SAFE(read_int16(&tmp16, f));
00610             nc->memos.memocount = (int16) tmp16;
00611             SAFE(read_int16(&tmp16, f));
00612             nc->memos.memomax = (int16) tmp16;
00613             if (nc->memos.memocount) {
00614                 Memo *memos;
00615                 memos = scalloc(sizeof(Memo) * nc->memos.memocount, 1);
00616                 nc->memos.memos = memos;
00617                 for (j = 0; j < nc->memos.memocount; j++, memos++) {
00618                     SAFE(read_int32(&memos->number, f));
00619                     SAFE(read_int16(&memos->flags, f));
00620                     SAFE(read_int32(&tmp32, f));
00621                     memos->time = tmp32;
00622                     SAFE(read_buffer(memos->sender, f));
00623                     SAFE(read_string(&memos->text, f));
00624                     memos->moduleData = NULL;
00625                 }
00626             }
00627 
00628             SAFE(read_int16(&nc->channelcount, f));
00629             SAFE(read_int16(&tmp16, f));
00630             nc->channelmax = CSMaxReg;
00631 
00632             if (ver < 13) {
00633                 /* Used to be dead authentication system */
00634                 SAFE(read_int16(&tmp16, f));
00635                 SAFE(read_int32(&tmp32, f));
00636                 SAFE(read_int16(&tmp16, f));
00637                 SAFE(read_string(&s, f));
00638             }
00639 
00640         }                       /* while (getc_db(f) != 0) */
00641         *nclast = NULL;
00642     }                           /* for (i) */
00643 
00644     for (i = 0; i < 1024 && !failed; i++) {
00645         nalast = &nalists[i];
00646         naprev = NULL;
00647         while ((c = getc_db(f)) == 1) {
00648             if (c != 1)
00649                 fatal("Invalid format in %s", NickDBName);
00650 
00651             na = scalloc(1, sizeof(NickAlias));
00652 
00653             SAFE(read_string(&na->nick, f));
00654 
00655             SAFE(read_string(&na->last_usermask, f));
00656             SAFE(read_string(&na->last_realname, f));
00657             SAFE(read_string(&na->last_quit, f));
00658 
00659             SAFE(read_int32(&tmp32, f));
00660             na->time_registered = tmp32;
00661             SAFE(read_int32(&tmp32, f));
00662             na->last_seen = tmp32;
00663             SAFE(read_int16(&na->status, f));
00664             na->status &= ~NS_TEMPORARY;
00665 
00666             SAFE(read_string(&s, f));
00667             na->nc = findcore(s);
00668             free(s);
00669 
00670             slist_add(&na->nc->aliases, na);
00671 
00672             if (!(na->status & NS_VERBOTEN)) {
00673                 if (!na->last_usermask)
00674                     na->last_usermask = sstrdup("");
00675                 if (!na->last_realname)
00676                     na->last_realname = sstrdup("");
00677             }
00678 
00679             na->nc->flags &= ~NI_SERVICES_ROOT;
00680 
00681             *nalast = na;
00682             nalast = &na->next;
00683             na->prev = naprev;
00684             naprev = na;
00685 
00686         }                       /* while (getc_db(f) != 0) */
00687 
00688         *nalast = NULL;
00689     }                           /* for (i) */
00690 
00691     close_db(f);
00692 
00693     for (i = 0; i < 1024; i++) {
00694         NickAlias *next;
00695 
00696         for (na = nalists[i]; na; na = next) {
00697             next = na->next;
00698             /* We check for coreless nicks (although it should never happen) */
00699             if (!na->nc) {
00700                 alog("%s: while loading database: %s has no core! We delete it.", s_NickServ, na->nick);
00701                 delnick(na);
00702                 continue;
00703             }
00704 
00705             /* Add the Services root flag if needed. */
00706             for (j = 0; j < RootNumber; j++)
00707                 if (!stricmp(ServicesRoots[j], na->nick))
00708                     na->nc->flags |= NI_SERVICES_ROOT;
00709         }
00710     }
00711 }
00712 
00713 #undef SAFE
00714 
00715 /*************************************************************************/
00716 
00717 #define SAFE(x) do {                        \
00718     if ((x) < 0) {                      \
00719     restore_db(f);                      \
00720     log_perror("Write error on %s", NickDBName);        \
00721     if (time(NULL) - lastwarn > WarningTimeout) {       \
00722         anope_cmd_global(NULL, "Write error on %s: %s", NickDBName, \
00723             strerror(errno));           \
00724         lastwarn = time(NULL);              \
00725     }                           \
00726     return;                         \
00727     }                               \
00728 } while (0)
00729 
00730 
00731 
00732 void save_ns_dbase(void)
00733 {
00734     dbFILE *f;
00735     int i, j;
00736     NickAlias *na;
00737     NickCore *nc;
00738     char **access;
00739     Memo *memos;
00740     static time_t lastwarn = 0;
00741 
00742     if (!(f = open_db(s_NickServ, NickDBName, "w", NICK_VERSION)))
00743         return;
00744 
00745     for (i = 0; i < 1024; i++) {
00746         for (nc = nclists[i]; nc; nc = nc->next) {
00747             SAFE(write_int8(1, f));
00748 
00749             SAFE(write_string(nc->display, f));
00750             SAFE(write_string(nc->pass, f));
00751 
00752             SAFE(write_string(nc->email, f));
00753             SAFE(write_string(nc->greet, f));
00754             SAFE(write_int32(nc->icq, f));
00755             SAFE(write_string(nc->url, f));
00756 
00757             SAFE(write_int32(nc->flags, f));
00758             SAFE(write_int16(nc->language, f));
00759 
00760             SAFE(write_int16(nc->accesscount, f));
00761             for (j = 0, access = nc->access; j < nc->accesscount;
00762                  j++, access++)
00763                 SAFE(write_string(*access, f));
00764 
00765             SAFE(write_int16(nc->memos.memocount, f));
00766             SAFE(write_int16(nc->memos.memomax, f));
00767             memos = nc->memos.memos;
00768             for (j = 0; j < nc->memos.memocount; j++, memos++) {
00769                 SAFE(write_int32(memos->number, f));
00770                 SAFE(write_int16(memos->flags, f));
00771                 SAFE(write_int32(memos->time, f));
00772                 SAFE(write_buffer(memos->sender, f));
00773                 SAFE(write_string(memos->text, f));
00774             }
00775 
00776             SAFE(write_int16(nc->channelcount, f));
00777             SAFE(write_int16(nc->channelmax, f));
00778 
00779         }                       /* for (nc) */
00780 
00781         SAFE(write_int8(0, f));
00782 
00783     }                           /* for (i) */
00784 
00785     for (i = 0; i < 1024; i++) {
00786         for (na = nalists[i]; na; na = na->next) {
00787             SAFE(write_int8(1, f));
00788 
00789             SAFE(write_string(na->nick, f));
00790 
00791             SAFE(write_string(na->last_usermask, f));
00792             SAFE(write_string(na->last_realname, f));
00793             SAFE(write_string(na->last_quit, f));
00794 
00795             SAFE(write_int32(na->time_registered, f));
00796             SAFE(write_int32(na->last_seen, f));
00797 
00798             SAFE(write_int16(na->status, f));
00799 
00800             SAFE(write_string(na->nc->display, f));
00801 
00802         }                       /* for (na) */
00803         SAFE(write_int8(0, f));
00804     }                           /* for (i) */
00805 
00806     close_db(f);
00807 
00808 }
00809 
00810 void save_ns_req_dbase(void)
00811 {
00812     dbFILE *f;
00813     int i;
00814     NickRequest *nr;
00815     static time_t lastwarn = 0;
00816 
00817     if (!(f = open_db(s_NickServ, PreNickDBName, "w", PRE_NICK_VERSION)))
00818         return;
00819 
00820     for (i = 0; i < 1024; i++) {
00821         for (nr = nrlists[i]; nr; nr = nr->next) {
00822             SAFE(write_int8(1, f));
00823             SAFE(write_string(nr->nick, f));
00824             SAFE(write_string(nr->passcode, f));
00825             SAFE(write_string(nr->password, f));
00826             SAFE(write_string(nr->email, f));
00827             SAFE(write_int32(nr->requested, f));
00828             SAFE(write_int8(0, f));
00829         }
00830     }
00831     close_db(f);
00832 
00833 }
00834 
00835 #undef SAFE
00836 
00837 void save_ns_rdb_dbase(void)
00838 {
00839 #ifdef USE_RDB
00840     int i;
00841     NickAlias *na;
00842     NickCore *nc;
00843 
00844     if (!rdb_open())
00845         return;
00846 
00847     if (rdb_tag_table("anope_ns_core") == 0) {
00848         alog("Unable to tag 'anope_ns_core' - NickServ RDB save failed.");
00849         return;
00850     }
00851     if (rdb_tag_table("anope_ns_alias") == 0) {
00852         alog("Unable to tag 'anope_ns_alias' - NickServ RDB save failed.");
00853         return;
00854     }
00855     if (rdb_tag_table("anope_ns_access") == 0) {
00856         alog("Unable to tag 'anope_ns_access' - NickServ RDB save failed.");
00857         return;
00858     }
00859     if (rdb_tag_table_where("anope_ms_info", "serv='NICK'") == 0) {
00860         alog("Unable to tag 'anope_ms_info' - NickServ RDB save failed.");
00861         return;
00862     }
00863 
00864     for (i = 0; i < 1024; i++) {
00865         for (nc = nclists[i]; nc; nc = nc->next) {
00866             if (rdb_save_ns_core(nc) == 0) {
00867                 alog("Unable to save NickCore for '%s' - NickServ RDB save failed.", nc->display);
00868                 return;
00869             }
00870         }                       /* for (nc) */
00871     }                           /* for (i) */
00872 
00873     for (i = 0; i < 1024; i++) {
00874         for (na = nalists[i]; na; na = na->next) {
00875             if (rdb_save_ns_alias(na) == 0) {
00876                 alog("Unable to save NickAlias for '%s' - NickServ RDB save failed.", na->nick);
00877                 return;
00878             }
00879         }                       /* for (na) */
00880     }                           /* for (i) */
00881 
00882     if (rdb_clean_table("anope_ns_core") == 0) {
00883         alog("Unable to clean table 'anope_ns_core' - NickServ RDB save failed.");
00884         return;
00885     }
00886     if (rdb_clean_table("anope_ns_alias") == 0) {
00887         alog("Unable to clean table 'anope_ns_alias' - NickServ RDB save failed.");
00888         return;
00889     }
00890     if (rdb_clean_table("anope_ns_access") == 0) {
00891         alog("Unable to clean table 'anope_ns_access' - NickServ RDB save failed.");
00892         return;
00893     }
00894     if (rdb_clean_table_where("anope_ms_info", "serv='NICK'") == 0) {
00895         alog("Unable to clean table 'anope_ms_info' - NickServ RDB save failed.");
00896         return;
00897     }
00898 
00899     rdb_close();
00900 #endif
00901 }
00902 
00903 void save_ns_req_rdb_dbase(void)
00904 {
00905 #ifdef USE_RDB
00906     int i;
00907     NickRequest *nr;
00908 
00909     if (!rdb_open())
00910         return;
00911 
00912     if (rdb_tag_table("anope_ns_request") == 0) {
00913         alog("Unable to tag table 'anope_ns_request' - NickServ Request RDB save failed.");
00914         return;
00915     }
00916 
00917     for (i = 0; i < 1024; i++) {
00918         for (nr = nrlists[i]; nr; nr = nr->next) {
00919             if (rdb_save_ns_req(nr) == 0) {
00920                 /* Something went wrong - abort saving */
00921                 alog("Unable to save NickRequest (nick '%s') - NickServ Request RDB save failed.", nr->nick);
00922                 return;
00923             }
00924         }
00925     }
00926 
00927     if (rdb_clean_table("anope_ns_request") == 0) {
00928         alog("Unable to clean table 'anope_ns_request' - NickServ Request RDB save failed.");
00929         return;
00930     }
00931 
00932     rdb_close();
00933 #endif
00934 
00935 }
00936 
00937 /*************************************************************************/
00938 
00939 /* Check whether a user is on the access list of the nick they're using If