00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "services.h"
00018 #include "pseudo.h"
00019
00020
00021
00022
00023 ChannelInfo *chanlists[256];
00024
00025 static int def_levels[][2] = {
00026 { CA_AUTOOP, 5 },
00027 { CA_AUTOVOICE, 3 },
00028 { CA_AUTODEOP, -1 },
00029 { CA_NOJOIN, -2 },
00030 { CA_INVITE, 5 },
00031 { CA_AKICK, 10 },
00032 { CA_SET, ACCESS_INVALID },
00033 { CA_CLEAR, ACCESS_INVALID },
00034 { CA_UNBAN, 5 },
00035 { CA_OPDEOP, 5 },
00036 { CA_ACCESS_LIST, 1 },
00037 { CA_ACCESS_CHANGE, 10 },
00038 { CA_MEMO, 10 },
00039 { CA_ASSIGN, ACCESS_INVALID },
00040 { CA_BADWORDS, 10 },
00041 { CA_NOKICK, 1 },
00042 { CA_FANTASIA, 3 },
00043 { CA_SAY, 5 },
00044 { CA_GREET, 5 },
00045 { CA_VOICEME, 3 },
00046 { CA_VOICE, 5 },
00047 { CA_GETKEY, 5 },
00048 { CA_AUTOHALFOP, 4 },
00049 { CA_AUTOPROTECT, 10 },
00050 { CA_OPDEOPME, 5 },
00051 { CA_HALFOPME, 4 },
00052 { CA_HALFOP, 5 },
00053 { CA_PROTECTME, 10 },
00054 { CA_PROTECT, ACCESS_INVALID },
00055 { CA_KICKME, 5 },
00056 { CA_KICK, 5 },
00057 { CA_SIGNKICK, ACCESS_INVALID },
00058 { CA_BANME, 5 },
00059 { CA_BAN, 5 },
00060 { CA_TOPIC, ACCESS_INVALID },
00061 { CA_INFO, ACCESS_INVALID },
00062 { -1 }
00063 };
00064
00065
00066 LevelInfo levelinfo[] = {
00067 { CA_AUTODEOP, "AUTODEOP", CHAN_LEVEL_AUTODEOP },
00068 { CA_AUTOHALFOP, "AUTOHALFOP", CHAN_LEVEL_AUTOHALFOP },
00069 { CA_AUTOOP, "AUTOOP", CHAN_LEVEL_AUTOOP },
00070 { CA_AUTOPROTECT, "", CHAN_LEVEL_AUTOPROTECT },
00071 { CA_AUTOVOICE, "AUTOVOICE", CHAN_LEVEL_AUTOVOICE },
00072 { CA_NOJOIN, "NOJOIN", CHAN_LEVEL_NOJOIN },
00073 { CA_SIGNKICK, "SIGNKICK", CHAN_LEVEL_SIGNKICK },
00074 { CA_ACCESS_LIST, "ACC-LIST", CHAN_LEVEL_ACCESS_LIST },
00075 { CA_ACCESS_CHANGE, "ACC-CHANGE", CHAN_LEVEL_ACCESS_CHANGE },
00076 { CA_AKICK, "AKICK", CHAN_LEVEL_AKICK },
00077 { CA_SET, "SET", CHAN_LEVEL_SET },
00078 { CA_BAN, "BAN", CHAN_LEVEL_BAN },
00079 { CA_BANME, "BANME", CHAN_LEVEL_BANME },
00080 { CA_CLEAR, "CLEAR", CHAN_LEVEL_CLEAR },
00081 { CA_GETKEY, "GETKEY", CHAN_LEVEL_GETKEY },
00082 { CA_HALFOP, "HALFOP", CHAN_LEVEL_HALFOP },
00083 { CA_HALFOPME, "HALFOPME", CHAN_LEVEL_HALFOPME },
00084 { CA_INFO, "INFO", CHAN_LEVEL_INFO },
00085 { CA_KICK, "KICK", CHAN_LEVEL_KICK },
00086 { CA_KICKME, "KICKME", CHAN_LEVEL_KICKME },
00087 { CA_INVITE, "INVITE", CHAN_LEVEL_INVITE },
00088 { CA_OPDEOP, "OPDEOP", CHAN_LEVEL_OPDEOP },
00089 { CA_OPDEOPME, "OPDEOPME", CHAN_LEVEL_OPDEOPME },
00090 { CA_PROTECT, "", CHAN_LEVEL_PROTECT },
00091 { CA_PROTECTME, "", CHAN_LEVEL_PROTECTME },
00092 { CA_TOPIC, "TOPIC", CHAN_LEVEL_TOPIC },
00093 { CA_UNBAN, "UNBAN", CHAN_LEVEL_UNBAN },
00094 { CA_VOICE, "VOICE", CHAN_LEVEL_VOICE },
00095 { CA_VOICEME, "VOICEME", CHAN_LEVEL_VOICEME },
00096 { CA_MEMO, "MEMO", CHAN_LEVEL_MEMO },
00097 { CA_ASSIGN, "ASSIGN", CHAN_LEVEL_ASSIGN },
00098 { CA_BADWORDS, "BADWORDS", CHAN_LEVEL_BADWORDS },
00099 { CA_FANTASIA, "FANTASIA", CHAN_LEVEL_FANTASIA },
00100 { CA_GREET, "GREET", CHAN_LEVEL_GREET },
00101 { CA_NOKICK, "NOKICK", CHAN_LEVEL_NOKICK },
00102 { CA_SAY, "SAY", CHAN_LEVEL_SAY },
00103 { -1 }
00104 };
00105 int levelinfo_maxwidth = 0;
00106
00107 CSModeUtil csmodeutils[] = {
00108 { "DEOP", "deop", "-o", CI_OPNOTICE, CA_OPDEOP, CA_OPDEOPME },
00109 { "OP", "op", "+o", CI_OPNOTICE, CA_OPDEOP, CA_OPDEOPME },
00110 { "DEVOICE", "devoice", "-v", 0, CA_VOICE, CA_VOICEME },
00111 { "VOICE", "voice", "+v", 0, CA_VOICE, CA_VOICEME },
00112 { "DEHALFOP", "dehalfop", "-h", 0, CA_HALFOP, CA_HALFOPME },
00113 { "HALFOP", "halfop", "+h", 0, CA_HALFOP, CA_HALFOPME },
00114 { "DEPROTECT", "", "", 0, CA_PROTECT, CA_PROTECTME },
00115 { "PROTECT", "", "", 0, CA_PROTECT, CA_PROTECTME },
00116 { NULL }
00117 };
00118
00119
00120
00121 void moduleAddChanServCmds(void) {
00122 modules_core_init(ChanServCoreNumber, ChanServCoreModules);
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 char *get_mlock_modes(ChannelInfo * ci, int complete)
00132 {
00133 static char res[BUFSIZE];
00134
00135 char *end = res;
00136
00137 if (ci->mlock_on || ci->mlock_off) {
00138 int n = 0;
00139 CBModeInfo *cbmi = cbmodeinfos;
00140
00141 if (ci->mlock_on) {
00142 *end++ = '+';
00143 n++;
00144
00145 do {
00146 if (ci->mlock_on & cbmi->flag)
00147 *end++ = cbmi->mode;
00148 } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1);
00149
00150 cbmi = cbmodeinfos;
00151 }
00152
00153 if (ci->mlock_off) {
00154 *end++ = '-';
00155 n++;
00156
00157 do {
00158 if (ci->mlock_off & cbmi->flag)
00159 *end++ = cbmi->mode;
00160 } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1);
00161
00162 cbmi = cbmodeinfos;
00163 }
00164
00165 if (ci->mlock_on && complete) {
00166 do {
00167 if (cbmi->csgetvalue && (ci->mlock_on & cbmi->flag)) {
00168 char *value = cbmi->csgetvalue(ci);
00169
00170 if (value) {
00171 *end++ = ' ';
00172 while (*value)
00173 *end++ = *value++;
00174 }
00175 }
00176 } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1);
00177 }
00178 }
00179
00180 *end = 0;
00181
00182 return res;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192 void listchans(int count_only, const char *chan)
00193 {
00194 int count = 0;
00195 ChannelInfo *ci;
00196 int i;
00197
00198 if (count_only) {
00199
00200 for (i = 0; i < 256; i++) {
00201 for (ci = chanlists[i]; ci; ci = ci->next)
00202 count++;
00203 }
00204 printf("%d channels registered.\n", count);
00205
00206 } else if (chan) {
00207
00208 struct tm *tm;
00209 char buf[BUFSIZE];
00210
00211 if (!(ci = cs_findchan(chan))) {
00212 printf("Channel %s not registered.\n", chan);
00213 return;
00214 }
00215 if (ci->flags & CI_VERBOTEN) {
00216 printf("Channel %s is FORBIDden.\n", ci->name);
00217 } else {
00218 printf("Information about channel %s:\n", ci->name);
00219 printf(" Founder: %s\n", ci->founder->display);
00220 printf(" Description: %s\n", ci->desc);
00221 tm = localtime(&ci->time_registered);
00222 strftime(buf, sizeof(buf),
00223 getstring(NULL, STRFTIME_DATE_TIME_FORMAT), tm);
00224 printf(" Registered: %s\n", buf);
00225 tm = localtime(&ci->last_used);
00226 strftime(buf, sizeof(buf),
00227 getstring(NULL, STRFTIME_DATE_TIME_FORMAT), tm);
00228 printf(" Last used: %s\n", buf);
00229 if (ci->last_topic) {
00230 printf(" Last topic: %s\n", ci->last_topic);
00231 printf(" Topic set by: %s\n", ci->last_topic_setter);
00232 }
00233 if (ci->url)
00234 printf(" URL: %s\n", ci->url);
00235 if (ci->email)
00236 printf(" E-mail address: %s\n", ci->email);
00237 printf(" Options: ");
00238 if (!ci->flags) {
00239 printf("None\n");
00240 } else {
00241 int need_comma = 0;
00242 static const char commastr[] = ", ";
00243 if (ci->flags & CI_PRIVATE) {
00244 printf("Private");
00245 need_comma = 1;
00246 }
00247 if (ci->flags & CI_KEEPTOPIC) {
00248 printf("%sTopic Retention",
00249 need_comma ? commastr : "");
00250 need_comma = 1;
00251 }
00252 if (ci->flags & CI_TOPICLOCK) {
00253 printf("%sTopic Lock", need_comma ? commastr : "");
00254 need_comma = 1;
00255 }
00256 if (ci->flags & CI_SECUREOPS) {
00257 printf("%sSecure Ops", need_comma ? commastr : "");
00258 need_comma = 1;
00259 }
00260 if (ci->flags & CI_RESTRICTED) {
00261 printf("%sRestricted Access",
00262 need_comma ? commastr : "");
00263 need_comma = 1;
00264 }
00265 if (ci->flags & CI_SECURE) {
00266 printf("%sSecure", need_comma ? commastr : "");
00267 need_comma = 1;
00268 }
00269 if (ci->flags & CI_NO_EXPIRE) {
00270 printf("%sNo Expire", need_comma ? commastr : "");
00271 need_comma = 1;
00272 }
00273 printf("\n");
00274 }
00275 if (ci->mlock_on || ci->mlock_off)
00276 printf(" Mode lock: %s\n", get_mlock_modes(ci, 1));
00277 }
00278
00279 } else {
00280
00281 for (i = 0; i < 256; i++) {
00282 for (ci = chanlists[i]; ci; ci = ci->next) {
00283 printf(" %s %-20s %s\n",
00284 ci->flags & CI_NO_EXPIRE ? "!" : " ", ci->name,
00285 ci->
00286 flags & CI_VERBOTEN ? "Disallowed (FORBID)" : ci->
00287 desc);
00288 count++;
00289 }
00290 }
00291 printf("%d channels registered.\n", count);
00292
00293 }
00294 }
00295
00296
00297
00298
00299
00300 void get_chanserv_stats(long *nrec, long *memuse)
00301 {
00302 long count = 0, mem = 0;
00303 int i, j;
00304 ChannelInfo *ci;
00305
00306 for (i = 0; i < 256; i++) {
00307 for (ci = chanlists[i]; ci; ci = ci->next) {
00308 count++;
00309 mem += sizeof(*ci);
00310 if (ci->desc)
00311 mem += strlen(ci->desc) + 1;
00312 if (ci->url)
00313 mem += strlen(ci->url) + 1;
00314 if (ci->email)
00315 mem += strlen(ci->email) + 1;
00316 mem += ci->accesscount * sizeof(ChanAccess);
00317 mem += ci->akickcount * sizeof(AutoKick);
00318 for (j = 0; j < ci->akickcount; j++) {
00319 if (!(ci->akick[j].flags & AK_ISNICK)
00320 && ci->akick[j].u.mask)
00321 mem += strlen(ci->akick[j].u.mask) + 1;
00322 if (ci->akick[j].reason)
00323 mem += strlen(ci->akick[j].reason) + 1;
00324 if (ci->akick[j].creator)
00325 mem += strlen(ci->akick[j].creator) + 1;
00326 }
00327 if (ci->mlock_key)
00328 mem += strlen(ci->mlock_key) + 1;
00329 if (ircd->fmode) {
00330 if (ci->mlock_flood)
00331 mem += strlen(ci->mlock_flood) + 1;
00332 }
00333 if (ircd->Lmode) {
00334 if (ci->mlock_redirect)
00335 mem += strlen(ci->mlock_redirect) + 1;
00336 }
00337 if (ci->last_topic)
00338 mem += strlen(ci->last_topic) + 1;
00339 if (ci->entry_message)
00340 mem += strlen(ci->entry_message) + 1;
00341 if (ci->forbidby)
00342 mem += strlen(ci->forbidby) + 1;
00343 if (ci->forbidreason)
00344 mem += strlen(ci->forbidreason) + 1;
00345 if (ci->levels)
00346 mem += sizeof(*ci->levels) * CA_SIZE;
00347 mem += ci->memos.memocount * sizeof(Memo);
00348 for (j = 0; j < ci->memos.memocount; j++) {
00349 if (ci->memos.memos[j].text)
00350 mem += strlen(ci->memos.memos[j].text) + 1;
00351 }
00352 if (ci->ttb)
00353 mem += sizeof(*ci->ttb) * TTB_SIZE;
00354 mem += ci->bwcount * sizeof(BadWord);
00355 for (j = 0; j < ci->bwcount; j++)
00356 if (ci->badwords[j].word)
00357 mem += strlen(ci->badwords[j].word) + 1;
00358 }
00359 }
00360 *nrec = count;
00361 *memuse = mem;
00362 }
00363
00364
00365
00366
00367
00368
00369 void cs_init(void)
00370 {
00371 moduleAddChanServCmds();
00372 }
00373
00374
00375
00376
00377
00378 void chanserv(User * u, char *buf)
00379 {
00380 char *cmd, *s;
00381
00382 cmd = strtok(buf, " ");
00383
00384 if (!cmd) {
00385 return;
00386 } else if (stricmp(cmd, "\1PING") == 0) {
00387 if (!(s = strtok(NULL, ""))) {
00388 s = "";
00389 }
00390 anope_cmd_ctcp(s_ChanServ, u->nick, "PING %s", s);
00391 } else if (skeleton) {
00392 notice_lang(s_ChanServ, u, SERVICE_OFFLINE, s_ChanServ);
00393 } else {
00394 mod_run_cmd(s_ChanServ, u, CHANSERV, cmd);
00395 }
00396 }
00397
00398
00399
00400
00401
00402
00403 #define SAFE(x) do { \
00404 if ((x) < 0) { \
00405 if (!forceload) \
00406 fatal("Read error on %s", ChanDBName); \
00407 failed = 1; \
00408 break; \
00409 } \
00410 } while (0)
00411
00412 void load_cs_dbase(void)
00413 {
00414 dbFILE *f;
00415 int ver, i, j, c;
00416 ChannelInfo *ci, **last, *prev;
00417 int failed = 0;
00418
00419 if (!(f = open_db(s_ChanServ, ChanDBName, "r", CHAN_VERSION)))
00420 return;
00421
00422 ver = get_file_version(f);
00423
00424 for (i = 0; i < 256 && !failed; i++) {
00425 uint16 tmp16;
00426 uint32 tmp32;
00427 int n_levels;
00428 char *s;
00429 NickAlias *na;
00430
00431 last = &chanlists[i];
00432 prev = NULL;
00433 while ((c = getc_db(f)) != 0) {
00434 if (c != 1)
00435 fatal("Invalid format in %s", ChanDBName);
00436 ci = scalloc(sizeof(ChannelInfo), 1);
00437 *last = ci;
00438 last = &ci->next;
00439 ci->prev = prev;
00440 prev = ci;
00441 SAFE(read_buffer(ci->name, f));
00442 SAFE(read_string(&s, f));
00443 if (s) {
00444 if (ver >= 13)
00445 ci->founder = findcore(s);
00446 else {
00447 na = findnick(s);
00448 if (na)
00449 ci->founder = na->nc;
00450 else
00451 ci->founder = NULL;
00452 }
00453 free(s);
00454 } else
00455 ci->founder = NULL;
00456 if (ver >= 7) {
00457 SAFE(read_string(&s, f));
00458 if (s) {
00459 if (ver >= 13)
00460 ci->successor = findcore(s);
00461 else {
00462 na = findnick(s);
00463 if (na)
00464 ci->successor = na->nc;
00465 else
00466 ci->successor = NULL;
00467 }
00468 free(s);
00469 } else
00470 ci->successor = NULL;
00471 } else {
00472 ci->successor = NULL;
00473 }
00474 SAFE(read_buffer(ci->founderpass, f));
00475 SAFE(read_string(&ci->desc, f));
00476 if (!ci->desc)
00477 ci->desc = sstrdup("");
00478 SAFE(read_string(&ci->url, f));
00479 SAFE(read_string(&ci->email, f));
00480 SAFE(read_int32(&tmp32, f));
00481 ci->time_registered = tmp32;
00482 SAFE(read_int32(&tmp32, f));
00483 ci->last_used = tmp32;
00484 SAFE(read_string(&ci->last_topic, f));
00485 SAFE(read_buffer(ci->last_topic_setter, f));
00486 SAFE(read_int32(&tmp32, f));
00487 ci->last_topic_time = tmp32;
00488 SAFE(read_int32(&ci->flags, f));
00489
00490
00491 if (ver <= 13 && (ci->flags & 0x00000020))
00492 ci->flags &= ~0x00000020;
00493
00494 ci->flags &= ~CI_INHABIT;
00495
00496 if (ver >= 9) {
00497 SAFE(read_string(&ci->forbidby, f));
00498 SAFE(read_string(&ci->forbidreason, f));
00499 } else {
00500 ci->forbidreason = NULL;
00501 ci->forbidby = NULL;
00502 }
00503 if (ver >= 9)
00504 SAFE(read_int16(&tmp16, f));
00505 else
00506 tmp16 = CSDefBantype;
00507 ci->bantype = tmp16;
00508 SAFE(read_int16(&tmp16, f));
00509 n_levels = tmp16;
00510 ci->levels = scalloc(2 * CA_SIZE, 1);
00511 reset_levels(ci);
00512 for (j = 0; j < n_levels; j++) {
00513 SAFE(read_int16(&tmp16, f));
00514 if (j < CA_SIZE)
00515 ci->levels[j] = (int16) tmp16;
00516 }
00517
00518 if (ver < 10)
00519 ci->levels[CA_OPDEOPME] = ci->levels[CA_OPDEOP];
00520 if (ver < 11) {
00521 ci->levels[CA_KICKME] = ci->levels[CA_OPDEOP];
00522 ci->levels[CA_KICK] = ci->levels[CA_OPDEOP];
00523 }
00524 if (ver < 15) {
00525
00526
00527
00528
00529 ci->levels[CA_AUTOPROTECT] = ci->levels[32];
00530 ci->levels[CA_PROTECTME] = ci->levels[33];
00531 ci->levels[CA_PROTECT] = ci->levels[34];
00532
00533 ci->levels[CA_BANME] = ci->levels[CA_OPDEOP];
00534 ci->levels[CA_BAN] = ci->levels[CA_OPDEOP];
00535 ci->levels[CA_TOPIC] = ACCESS_INVALID;
00536
00537
00538 }
00539
00540 SAFE(read_int16(&ci->accesscount, f));
00541 if (ci->accesscount) {
00542 ci->access = scalloc(ci->accesscount, sizeof(ChanAccess));
00543 for (j = 0; j < ci->accesscount; j++) {
00544 SAFE(read_int16(&ci->access[j].in_use, f));
00545 if (ci->access[j].in_use) {
00546 SAFE(read_int16(&tmp16, f));
00547 ci->access[j].level = (int16) tmp16;
00548 SAFE(read_string(&s, f));
00549 if (s) {
00550 if (ver >= 13)
00551 ci->access[j].nc = findcore(s);
00552 else {
00553 na = findnick(s);
00554 if (na)
00555 ci->access[j].nc = na->nc;
00556 else
00557 ci->access[j].nc = NULL;
00558 }
00559 free(s);
00560 }
00561 if (ci->access[j].nc == NULL)
00562 ci->access[j].in_use = 0;
00563 if (ver >= 11) {
00564 SAFE(read_int32(&tmp32, f));
00565 ci->access[j].last_seen = tmp32;
00566 } else {
00567 ci->access[j].last_seen = 0;
00568 }
00569 }
00570 }
00571 } else {
00572 ci->access = NULL;
00573 }
00574
00575 SAFE(read_int16(&ci->akickcount, f));
00576 if (ci->akickcount) {
00577 ci->akick = scalloc(ci->akickcount, sizeof(AutoKick));
00578 for (j = 0; j < ci->akickcount; j++) {
00579 if (ver >= 15) {
00580 SAFE(read_int16(&ci->akick[j].flags, f));
00581 } else {
00582 SAFE(read_int16(&tmp16, f));
00583 if (tmp16)
00584 ci->akick[j].flags |= AK_USED;
00585 }
00586 if (ci->akick[j].flags & AK_USED) {
00587 if (ver < 15) {
00588 SAFE(read_int16(&tmp16, f));
00589 if (tmp16)
00590 ci->akick[j].flags |= AK_ISNICK;
00591 }
00592 SAFE(read_string(&s, f));
00593 if (ci->akick[j].flags & AK_ISNICK) {
00594 if (ver >= 13) {
00595 ci->akick[j].u.nc = findcore(s);
00596 } else {
00597 na = findnick(s);
00598 if (na)
00599 ci->akick[j].u.nc = na->nc;
00600 else
00601 ci->akick[j].u.nc = NULL;
00602 }
00603 if (!ci->akick[j].u.nc)
00604 ci->akick[j].flags &= ~AK_USED;
00605 free(s);
00606 } else {
00607 ci->akick[j].u.mask = s;
00608 }
00609 SAFE(read_string(&s, f));
00610 if (ci->akick[j].flags & AK_USED)
00611 ci->akick[j].reason = s;
00612 else if (s)
00613 free(s);
00614 if (ver >= 9) {
00615 SAFE(read_string(&s, f));
00616 if (ci->akick[j].flags & AK_USED) {
00617 ci->akick[j].creator = s;
00618 } else if (s) {
00619 free(s);
00620 }
00621 SAFE(read_int32(&tmp32, f));
00622 if (ci->akick[j].flags & AK_USED)
00623 ci->akick[j].addtime = tmp32;
00624 } else {
00625 ci->akick[j].creator = NULL;
00626 ci->akick[j].addtime = 0;
00627 }
00628 }
00629
00630
00631 if ((ver == 15) && ci->akick[j].flags > 8) {
00632 ci->akick[j].flags = 0;
00633 ci->akick[j].u.nc = NULL;
00634 ci->akick[j].u.nc = NULL;
00635 ci->akick[j].addtime = 0;
00636 ci->akick[j].creator = NULL;
00637 ci->akick[j].reason = NULL;
00638 }
00639 }
00640 } else {
00641 ci->akick = NULL;
00642 }
00643
00644 if (ver >= 10) {
00645 SAFE(read_int32(&ci->mlock_on, f));
00646 SAFE(read_int32(&ci->mlock_off, f));
00647 } else {
00648 SAFE(read_int16(&tmp16, f));
00649 ci->mlock_on = tmp16;
00650 SAFE(read_int16(&tmp16, f));
00651 ci->mlock_off = tmp16;
00652 }
00653 SAFE(read_int32(&ci->mlock_limit, f));
00654 SAFE(read_string(&ci->mlock_key, f));
00655 if (ver >= 10) {
00656 if (ircd->fmode) {
00657 SAFE(read_string(&ci->mlock_flood, f));
00658 } else {
00659 SAFE(read_string(&s, f));
00660 if (s)
00661 free(s);
00662 }
00663 if (ircd->Lmode) {
00664 SAFE(read_string(&ci->mlock_redirect, f));
00665 } else {
00666 SAFE(read_string(&s, f));
00667 if (s)
00668 free(s);
00669 }
00670 }
00671
00672 SAFE(read_int16(&tmp16, f));
00673 ci->memos.memocount = (int16) tmp16;
00674 SAFE(read_int16(&tmp16, f));
00675 ci->memos.memomax = (int16) tmp16;
00676 if (ci->memos.memocount) {
00677 Memo *memos;
00678 memos = scalloc(sizeof(Memo) * ci->memos.memocount, 1);
00679 ci->memos.memos = memos;
00680 for (j = 0; j < ci->memos.memocount; j++, memos++) {
00681 SAFE(read_int32(&memos->number, f));
00682 SAFE(read_int16(&memos->flags, f));
00683 SAFE(read_int32(&tmp32, f));
00684 memos->time = tmp32;
00685 SAFE(read_buffer(memos->sender, f));
00686 SAFE(read_string(&memos->text, f));
00687 memos->moduleData = NULL;
00688 }
00689 }
00690
00691 SAFE(read_string(&ci->entry_message, f));
00692
00693 ci->c = NULL;
00694
00695
00696 if (ver <= 11) {
00697
00698 if (!(ci->flags & CI_VERBOTEN)
00699 && ci->successor == ci->founder) {
00700 alog("Warning: founder and successor of %s are equal. Cleaning up.", ci->name);
00701 ci->successor = NULL;
00702 }
00703 }
00704
00705
00706
00707 if (ver >= 8) {
00708 int n_ttb;
00709
00710 SAFE(read_string(&s, f));
00711 if (s) {
00712 ci->bi = findbot(s);
00713 free(s);
00714 } else
00715 ci->bi = NULL;
00716
00717 SAFE(read_int32(&tmp32, f));
00718 ci->botflags = tmp32;
00719 SAFE(read_int16(&tmp16, f));
00720 n_ttb = tmp16;
00721 ci->ttb = scalloc(2 * TTB_SIZE, 1);
00722 for (j = 0; j < n_ttb; j++) {
00723 SAFE(read_int16(&tmp16, f));
00724 if (j < TTB_SIZE)
00725 ci->ttb[j] = (int16) tmp16;
00726 }
00727 for (j = n_ttb; j < TTB_SIZE; j++)
00728 ci->ttb[j] = 0;
00729 SAFE(read_int16(&tmp16, f));
00730 ci->capsmin = tmp16;
00731 SAFE(read_int16(&tmp16, f));
00732 ci->capspercent = tmp16;
00733 SAFE(read_int16(&tmp16, f));
00734 ci->floodlines = tmp16;
00735 SAFE(read_int16(&tmp16, f));
00736 ci->floodsecs = tmp16;
00737 SAFE(read_int16(&tmp16, f));
00738 ci->repeattimes = tmp16;
00739
00740 SAFE(read_int16(&ci->bwcount, f));
00741 if (ci->bwcount) {
00742 ci->badwords = scalloc(ci->bwcount, sizeof(BadWord));
00743 for (j = 0; j < ci->bwcount; j++) {
00744 SAFE(read_int16(&ci->badwords[j].in_use, f));
00745 if (ci->badwords[j].in_use) {
00746 SAFE(read_string(&ci->badwords[j].word, f));
00747 SAFE(read_int16(&ci->badwords[j].type, f));
00748 }
00749 }
00750 } else {
00751 ci->badwords = NULL;
00752 }
00753 } else {
00754 ci->bi = NULL;
00755 ci->botflags = 0;
00756 ci->ttb = scalloc(2 * TTB_SIZE, 1);
00757 for (j = 0; j < TTB_SIZE; j++)
00758 ci->ttb[j] = 0;
00759 ci->bwcount = 0;
00760 ci->badwords = NULL;
00761 }
00762
00763 }
00764
00765 *last = NULL;
00766
00767 }
00768
00769 close_db(f);
00770
00771
00772
00773 for (i = 0; i < 256; i++) {
00774 ChannelInfo *next;
00775 for (ci = chanlists[i]; ci; ci = next) {
00776 next = ci->next;
00777 if (!(ci->flags & CI_VERBOTEN) && !ci->founder) {
00778 alog("%s: database load: Deleting founderless channel %s",
00779 s_ChanServ, ci->name);
00780 delchan(ci);
00781 continue;
00782 }
00783 if (ver < 13) {
00784 ChanAccess *access, *access2;
00785 AutoKick *akick, *akick2;
00786 int k;
00787
00788 if (ci->flags & CI_VERBOTEN)
00789 continue;
00790
00791 ci->founder->channelcount++;
00792
00793 for (j = 0, access = ci->access; j < ci->accesscount;
00794 j++, access++) {
00795 if (!access->in_use)
00796 continue;
00797 for (k = 0, access2 = ci->access; k < j;
00798 k++, access2++) {
00799 if (access2->in_use && access2->nc == access->nc) {
00800 alog("%s: deleting %s channel access entry of %s because it is already in the list (this is OK).", s_ChanServ, access->nc->display, ci->name);
00801 memset(access, 0, sizeof(ChanAccess));
00802 break;
00803 }
00804 }
00805 }
00806 for (j = 0, akick = ci->akick; j < ci->akickcount;
00807 j++, akick++) {
00808 if (!(akick->flags & AK_USED)
00809 || !(akick->flags & AK_ISNICK))
00810 continue;
00811 for (k = 0, akick2 = ci->akick; k < j; k++, akick2++) {
00812 if ((akick2->flags & AK_USED)
00813 && (akick2->flags & AK_ISNICK)
00814 && akick2->u.nc == akick->u.nc) {
00815 alog("%s: deleting %s channel akick entry of %s because it is already in the list (this is OK).", s_ChanServ, akick->u.nc->display, ci->name);
00816 if (akick->reason)
00817 free(akick->reason);
00818 if (akick->creator)
00819 free(akick->creator);
00820 memset(akick, 0, sizeof(AutoKick));
00821 break;
00822 }
00823 }
00824 }
00825 }
00826 }
00827 }
00828 }
00829
00830 #undef SAFE
00831
00832
00833
00834 #define SAFE(x) do { \
00835 if ((x) < 0) { \
00836 restore_db(f); \
00837 log_perror("Write error on %s", ChanDBName); \
00838 if (time(NULL) - lastwarn > WarningTimeout) { \
00839 anope_cmd_global(NULL, "Write error on %s: %s", ChanDBName, \
00840 strerror(errno)); \
00841 lastwarn = time(NULL); \
00842 } \
00843 return; \
00844 } \
00845 } while (0)
00846
00847 void save_cs_dbase(void)
00848 {
00849 dbFILE *f;
00850 int i, j;
00851 ChannelInfo *ci;
00852 Memo *memos;
00853 static time_t lastwarn = 0;
00854
00855 if (!(f = open_db(s_ChanServ, ChanDBName, "w", CHAN_VERSION)))
00856 return;
00857
00858 for (i = 0; i < 256; i++) {
00859 int16 tmp16;
00860
00861 for (ci = chanlists[i]; ci; ci = ci->next) {
00862 SAFE(write_int8(1, f));
00863 SAFE(write_buffer(ci->name, f));
00864 if (ci->founder)
00865 SAFE(write_string(ci->founder->display, f));
00866 else
00867 SAFE(write_string(NULL, f));
00868 if (ci->successor)
00869 SAFE(write_string(ci->successor->display, f));
00870 else
00871 SAFE(write_string(NULL, f));
00872 SAFE(write_buffer(ci->founde