00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "services.h"
00017 #include "pseudo.h"
00018
00019
00020
00021
00022 ChannelInfo *chanlists[256];
00023
00024 static int def_levels[][2] = {
00025 { CA_AUTOOP, 5 },
00026 { CA_AUTOVOICE, 3 },
00027 { CA_AUTODEOP, -1 },
00028 { CA_NOJOIN, -2 },
00029 { CA_INVITE, 5 },
00030 { CA_AKICK, 10 },
00031 { CA_SET, ACCESS_INVALID },
00032 { CA_CLEAR, ACCESS_INVALID },
00033 { CA_UNBAN, 5 },
00034 { CA_OPDEOP, 5 },
00035 { CA_ACCESS_LIST, 1 },
00036 { CA_ACCESS_CHANGE, 10 },
00037 { CA_MEMO, 10 },
00038 { CA_ASSIGN, ACCESS_INVALID },
00039 { CA_BADWORDS, 10 },
00040 { CA_NOKICK, 1 },
00041 { CA_FANTASIA, 3 },
00042 { CA_SAY, 5 },
00043 { CA_GREET, 5 },
00044 { CA_VOICEME, 3 },
00045 { CA_VOICE, 5 },
00046 { CA_GETKEY, 5 },
00047 { CA_AUTOHALFOP, 4 },
00048 { CA_AUTOPROTECT, 10 },
00049 { CA_OPDEOPME, 5 },
00050 { CA_HALFOPME, 4 },
00051 { CA_HALFOP, 5 },
00052 { CA_PROTECTME, 10 },
00053 { CA_PROTECT, ACCESS_INVALID },
00054 { CA_KICKME, 5 },
00055 { CA_KICK, 5 },
00056 { CA_SIGNKICK, ACCESS_INVALID },
00057 { CA_BANME, 5 },
00058 { CA_BAN, 5 },
00059 { CA_TOPIC, ACCESS_INVALID },
00060 { CA_INFO, ACCESS_INVALID },
00061 { -1 }
00062 };
00063
00064
00065 LevelInfo levelinfo[] = {
00066 { CA_AUTODEOP, "AUTODEOP", CHAN_LEVEL_AUTODEOP },
00067 { CA_AUTOHALFOP, "AUTOHALFOP", CHAN_LEVEL_AUTOHALFOP },
00068 { CA_AUTOOP, "AUTOOP", CHAN_LEVEL_AUTOOP },
00069 { CA_AUTOPROTECT, "", CHAN_LEVEL_AUTOPROTECT },
00070 { CA_AUTOVOICE, "AUTOVOICE", CHAN_LEVEL_AUTOVOICE },
00071 { CA_NOJOIN, "NOJOIN", CHAN_LEVEL_NOJOIN },
00072 { CA_SIGNKICK, "SIGNKICK", CHAN_LEVEL_SIGNKICK },
00073 { CA_ACCESS_LIST, "ACC-LIST", CHAN_LEVEL_ACCESS_LIST },
00074 { CA_ACCESS_CHANGE, "ACC-CHANGE", CHAN_LEVEL_ACCESS_CHANGE },
00075 { CA_AKICK, "AKICK", CHAN_LEVEL_AKICK },
00076 { CA_SET, "SET", CHAN_LEVEL_SET },
00077 { CA_BAN, "BAN", CHAN_LEVEL_BAN },
00078 { CA_BANME, "BANME", CHAN_LEVEL_BANME },
00079 { CA_CLEAR, "CLEAR", CHAN_LEVEL_CLEAR },
00080 { CA_GETKEY, "GETKEY", CHAN_LEVEL_GETKEY },
00081 { CA_HALFOP, "HALFOP", CHAN_LEVEL_HALFOP },
00082 { CA_HALFOPME, "HALFOPME", CHAN_LEVEL_HALFOPME },
00083 { CA_INFO, "INFO", CHAN_LEVEL_INFO },
00084 { CA_KICK, "KICK", CHAN_LEVEL_KICK },
00085 { CA_KICKME, "KICKME", CHAN_LEVEL_KICKME },
00086 { CA_INVITE, "INVITE", CHAN_LEVEL_INVITE },
00087 { CA_OPDEOP, "OPDEOP", CHAN_LEVEL_OPDEOP },
00088 { CA_OPDEOPME, "OPDEOPME", CHAN_LEVEL_OPDEOPME },
00089 { CA_PROTECT, "", CHAN_LEVEL_PROTECT },
00090 { CA_PROTECTME, "", CHAN_LEVEL_PROTECTME },
00091 { CA_TOPIC, "TOPIC", CHAN_LEVEL_TOPIC },
00092 { CA_UNBAN, "UNBAN", CHAN_LEVEL_UNBAN },
00093 { CA_VOICE, "VOICE", CHAN_LEVEL_VOICE },
00094 { CA_VOICEME, "VOICEME", CHAN_LEVEL_VOICEME },
00095 { CA_MEMO, "MEMO", CHAN_LEVEL_MEMO },
00096 { CA_ASSIGN, "ASSIGN", CHAN_LEVEL_ASSIGN },
00097 { CA_BADWORDS, "BADWORDS", CHAN_LEVEL_BADWORDS },
00098 { CA_FANTASIA, "FANTASIA", CHAN_LEVEL_FANTASIA },
00099 { CA_GREET, "GREET", CHAN_LEVEL_GREET },
00100 { CA_NOKICK, "NOKICK", CHAN_LEVEL_NOKICK },
00101 { CA_SAY, "SAY", CHAN_LEVEL_SAY },
00102 { -1 }
00103 };
00104 int levelinfo_maxwidth = 0;
00105
00106 CSModeUtil csmodeutils[] = {
00107 { "DEOP", "deop", "-o", CI_OPNOTICE, CA_OPDEOP, CA_OPDEOPME },
00108 { "OP", "op", "+o", CI_OPNOTICE, CA_OPDEOP, CA_OPDEOPME },
00109 { "DEVOICE", "devoice", "-v", 0, CA_VOICE, CA_VOICEME },
00110 { "VOICE", "voice", "+v", 0, CA_VOICE, CA_VOICEME },
00111 { "DEHALFOP", "dehalfop", "-h", 0, CA_HALFOP, CA_HALFOPME },
00112 { "HALFOP", "halfop", "+h", 0, CA_HALFOP, CA_HALFOPME },
00113 { "DEPROTECT", "", "", 0, CA_PROTECT, CA_PROTECTME },
00114 { "PROTECT", "", "", 0, CA_PROTECT, CA_PROTECTME },
00115 { NULL }
00116 };
00117
00118
00119
00120 void moduleAddChanServCmds(void) {
00121 modules_core_init(ChanServCoreNumber, ChanServCoreModules);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 char *get_mlock_modes(ChannelInfo * ci, int complete)
00131 {
00132 static char res[BUFSIZE];
00133
00134 char *end = res;
00135
00136 if (ci->mlock_on || ci->mlock_off) {
00137 int n = 0;
00138 CBModeInfo *cbmi = cbmodeinfos;
00139
00140 if (ci->mlock_on) {
00141 *end++ = '+';
00142 n++;
00143
00144 do {
00145 if (ci->mlock_on & cbmi->flag)
00146 *end++ = cbmi->mode;
00147 } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
00148
00149 cbmi = cbmodeinfos;
00150 }
00151
00152 if (ci->mlock_off) {
00153 *end++ = '-';
00154 n++;
00155
00156 do {
00157 if (ci->mlock_off & cbmi->flag)
00158 *end++ = cbmi->mode;
00159 } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
00160
00161 cbmi = cbmodeinfos;
00162 }
00163
00164 if (ci->mlock_on && complete) {
00165 do {
00166 if (cbmi->csgetvalue && (ci->mlock_on & cbmi->flag)) {
00167 char *value = cbmi->csgetvalue(ci);
00168
00169 if (value) {
00170 *end++ = ' ';
00171 while (*value)
00172 *end++ = *value++;
00173 }
00174 }
00175 } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
00176 }
00177 }
00178
00179 *end = 0;
00180
00181 return res;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191 void listchans(int count_only, const char *chan)
00192 {
00193 int count = 0;
00194 ChannelInfo *ci;
00195 int i;
00196
00197 if (count_only) {
00198
00199 for (i = 0; i < 256; i++) {
00200 for (ci = chanlists[i]; ci; ci = ci->next)
00201 count++;
00202 }
00203 printf("%d channels registered.\n", count);
00204
00205 } else if (chan) {
00206
00207 struct tm *tm;
00208 char buf[BUFSIZE];
00209
00210 if (!(ci = cs_findchan(chan))) {
00211 printf("Channel %s not registered.\n", chan);
00212 return;
00213 }
00214 if (ci->flags & CI_VERBOTEN) {
00215 printf("Channel %s is FORBIDden.\n", ci->name);
00216 } else {
00217 printf("Information about channel %s:\n", ci->name);
00218 printf(" Founder: %s\n", ci->founder->display);
00219 printf(" Description: %s\n", ci->desc);
00220 tm = localtime(&ci->time_registered);
00221 strftime(buf, sizeof(buf),
00222 getstring(NULL, STRFTIME_DATE_TIME_FORMAT), tm);
00223 printf(" Registered: %s\n", buf);
00224 tm = localtime(&ci->last_used);
00225 strftime(buf, sizeof(buf),
00226 getstring(NULL, STRFTIME_DATE_TIME_FORMAT), tm);
00227 printf(" Last used: %s\n", buf);
00228 if (ci->last_topic) {
00229 printf(" Last topic: %s\n", ci->last_topic);
00230 printf(" Topic set by: %s\n", ci->last_topic_setter);
00231 }
00232 if (ci->url)
00233 printf(" URL: %s\n", ci->url);
00234 if (ci->email)
00235 printf(" E-mail address: %s\n", ci->email);
00236 printf(" Options: ");
00237 if (!ci->flags) {
00238 printf("None\n");
00239 } else {
00240 int need_comma = 0;
00241 static const char commastr[] = ", ";
00242 if (ci->flags & CI_PRIVATE) {
00243 printf("Private");
00244 need_comma = 1;
00245 }
00246 if (ci->flags & CI_KEEPTOPIC) {
00247 printf("%sTopic Retention",
00248 need_comma ? commastr : "");
00249 need_comma = 1;
00250 }
00251 if (ci->flags & CI_TOPICLOCK) {
00252 printf("%sTopic Lock", need_comma ? commastr : "");
00253 need_comma = 1;
00254 }
00255 if (ci->flags & CI_SECUREOPS) {
00256 printf("%sSecure Ops", need_comma ? commastr : "");
00257 need_comma = 1;
00258 }
00259 if (ci->flags & CI_RESTRICTED) {
00260 printf("%sRestricted Access",
00261 need_comma ? commastr : "");
00262 need_comma = 1;
00263 }
00264 if (ci->flags & CI_SECURE) {
00265 printf("%sSecure", need_comma ? commastr : "");
00266 need_comma = 1;
00267 }
00268 if (ci->flags & CI_NO_EXPIRE) {
00269 printf("%sNo Expire", need_comma ? commastr : "");
00270 need_comma = 1;
00271 }
00272 printf("\n");
00273 }
00274 if (ci->mlock_on || ci->mlock_off) {
00275 printf(" Mode lock: %s\n", get_mlock_modes(ci, 1));
00276 }
00277 if (ci->flags & CI_SUSPENDED) {
00278 printf
00279 ("This nickname is currently suspended by %s, reason: %s\n",
00280 ci->forbidby,
00281 (ci->forbidreason ? ci->forbidreason : "No reason"));
00282 }
00283 }
00284
00285 } else {
00286
00287 for (i = 0; i < 256; i++) {
00288 for (ci = chanlists[i]; ci; ci = ci->next) {
00289 printf(" %s %-20s %s\n",
00290 ci->flags & CI_NO_EXPIRE ? "!" : " ", ci->name,
00291 ci->flags & CI_VERBOTEN ?
00292 "Disallowed (FORBID)" : (ci->flags & CI_SUSPENDED ?
00293 "Disallowed (SUSPENDED)" :
00294 ci->desc));
00295 count++;
00296 }
00297 }
00298 printf("%d channels registered.\n", count);
00299
00300 }
00301 }
00302
00303
00304
00305
00306
00307 void get_chanserv_stats(long *nrec, long *memuse)
00308 {
00309 long count = 0, mem = 0;
00310 int i, j;
00311 ChannelInfo *ci;
00312
00313 for (i = 0; i < 256; i++) {
00314 for (ci = chanlists[i]; ci; ci = ci->next) {
00315 count++;
00316 mem += sizeof(*ci);
00317 if (ci->desc)
00318 mem += strlen(ci->desc) + 1;
00319 if (ci->url)
00320 mem += strlen(ci->url) + 1;
00321 if (ci->email)
00322 mem += strlen(ci->email) + 1;
00323 mem += ci->accesscount * sizeof(ChanAccess);
00324 mem += ci->akickcount * sizeof(AutoKick);
00325 for (j = 0; j < ci->akickcount; j++) {
00326 if (!(ci->akick[j].flags & AK_ISNICK)
00327 && ci->akick[j].u.mask)
00328 mem += strlen(ci->akick[j].u.mask) + 1;
00329 if (ci->akick[j].reason)
00330 mem += strlen(ci->akick[j].reason) + 1;
00331 if (ci->akick[j].creator)
00332 mem += strlen(ci->akick[j].creator) + 1;
00333 }
00334 if (ci->mlock_key)
00335 mem += strlen(ci->mlock_key) + 1;
00336 if (ircd->fmode) {
00337 if (ci->mlock_flood)
00338 mem += strlen(ci->mlock_flood) + 1;
00339 }
00340 if (ircd->Lmode) {
00341 if (ci->mlock_redirect)
00342 mem += strlen(ci->mlock_redirect) + 1;
00343 }
00344 if (ircd->jmode) {
00345 if (ci->mlock_throttle)
00346 mem += strlen(ci->mlock_throttle) + 1;
00347 }
00348 if (ci->last_topic)
00349 mem += strlen(ci->last_topic) + 1;
00350 if (ci->entry_message)
00351 mem += strlen(ci->entry_message) + 1;
00352 if (ci->forbidby)
00353 mem += strlen(ci->forbidby) + 1;
00354 if (ci->forbidreason)
00355 mem += strlen(ci->forbidreason) + 1;
00356 if (ci->levels)
00357 mem += sizeof(*ci->levels) * CA_SIZE;
00358 mem += ci->memos.memocount * sizeof(Memo);
00359 for (j = 0; j < ci->memos.memocount; j++) {
00360 if (ci->memos.memos[j].text)
00361 mem += strlen(ci->memos.memos[j].text) + 1;
00362 }
00363 if (ci->ttb)
00364 mem += sizeof(*ci->ttb) * TTB_SIZE;
00365 mem += ci->bwcount * sizeof(BadWord);
00366 for (j = 0; j < ci->bwcount; j++)
00367 if (ci->badwords[j].word)
00368 mem += strlen(ci->badwords[j].word) + 1;
00369 }
00370 }
00371 *nrec = count;
00372 *memuse = mem;
00373 }
00374
00375
00376
00377
00378
00379
00380 void cs_init(void)
00381 {
00382 moduleAddChanServCmds();
00383 }
00384
00385
00386
00387
00388
00389 void chanserv(User * u, char *buf)
00390 {
00391 char *cmd, *s;
00392
00393 cmd = strtok(buf, " ");
00394
00395 if (!cmd) {
00396 return;
00397 } else if (stricmp(cmd, "\1PING") == 0) {
00398 if (!(s = strtok(NULL, ""))) {
00399 s = "";
00400 }
00401 anope_cmd_ctcp(s_ChanServ, u->nick, "PING %s", s);
00402 } else if (skeleton) {
00403 notice_lang(s_ChanServ, u, SERVICE_OFFLINE, s_ChanServ);
00404 } else {
00405 mod_run_cmd(s_ChanServ, u, CHANSERV, cmd);
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414 #define SAFE(x) do { \
00415 if ((x) < 0) { \
00416 if (!forceload) \
00417 fatal("Read error on %s", ChanDBName); \
00418 failed = 1; \
00419 break; \
00420 } \
00421 } while (0)
00422
00423 void load_cs_dbase(void)
00424 {
00425 dbFILE *f;
00426 int ver, i, j, c;
00427 ChannelInfo *ci, **last, *prev;
00428 int failed = 0;
00429
00430 if (!(f = open_db(s_ChanServ, ChanDBName, "r", CHAN_VERSION)))
00431 return;
00432
00433 ver = get_file_version(f);
00434
00435 for (i = 0; i < 256 && !failed; i++) {
00436 uint16 tmp16;
00437 uint32 tmp32;
00438 int n_levels;
00439 char *s;
00440 NickAlias *na;
00441
00442 last = &chanlists[i];
00443 prev = NULL;
00444 while ((c = getc_db(f)) != 0) {
00445 if (c != 1)
00446 fatal("Invalid format in %s", ChanDBName);
00447 ci = scalloc(sizeof(ChannelInfo), 1);
00448 *last = ci;
00449 last = &ci->next;
00450 ci->prev = prev;
00451 prev = ci;
00452 SAFE(read_buffer(ci->name, f));
00453 SAFE(read_string(&s, f));
00454 if (s) {
00455 if (ver >= 13)
00456 ci->founder = findcore(s);
00457 else {
00458 na = findnick(s);
00459 if (na)
00460 ci->founder = na->nc;
00461 else
00462 ci->founder = NULL;
00463 }
00464 free(s);
00465 } else
00466 ci->founder = NULL;
00467 if (ver >= 7) {
00468 SAFE(read_string(&s, f));
00469 if (s) {
00470 if (ver >= 13)
00471 ci->successor = findcore(s);
00472 else {
00473 na = findnick(s);
00474 if (na)
00475 ci->successor = na->nc;
00476 else
00477 ci->successor = NULL;
00478 }
00479 free(s);
00480 } else
00481 ci->successor = NULL;
00482 } else {
00483 ci->successor = NULL;
00484 }
00485 SAFE(read_buffer(ci->founderpass, f));
00486 SAFE(read_string(&ci->desc, f));
00487 if (!ci->desc)
00488 ci->desc = sstrdup("");
00489 SAFE(read_string(&ci->url, f));
00490 SAFE(read_string(&ci->email, f));
00491 SAFE(read_int32(&tmp32, f));
00492 ci->time_registered = tmp32;
00493 SAFE(read_int32(&tmp32, f));
00494 ci->last_used = tmp32;
00495 SAFE(read_string(&ci->last_topic, f));
00496 SAFE(read_buffer(ci->last_topic_setter, f));
00497 SAFE(read_int32(&tmp32, f));
00498 ci->last_topic_time = tmp32;
00499 SAFE(read_int32(&ci->flags, f));
00500
00501
00502 if (ver <= 13 && (ci->flags & 0x00000020))
00503 ci->flags &= ~0x00000020;
00504
00505 ci->flags &= ~CI_INHABIT;
00506
00507 if (ver >= 9) {
00508 SAFE(read_string(&ci->forbidby, f));
00509 SAFE(read_string(&ci->forbidreason, f));
00510 } else {
00511 ci->forbidreason = NULL;
00512 ci->forbidby = NULL;
00513 }
00514 if (ver >= 9)
00515 SAFE(read_int16(&tmp16, f));
00516 else
00517 tmp16 = CSDefBantype;
00518 ci->bantype = tmp16;
00519 SAFE(read_int16(&tmp16, f));
00520 n_levels = tmp16;
00521 ci->levels = scalloc(2 * CA_SIZE, 1);
00522 reset_levels(ci);
00523 for (j = 0; j < n_levels; j++) {
00524 SAFE(read_int16(&tmp16, f));
00525 if (j < CA_SIZE)
00526 ci->levels[j] = (int16) tmp16;
00527 }
00528
00529 if (ver < 10)
00530 ci->levels[CA_OPDEOPME] = ci->levels[CA_OPDEOP];
00531 if (ver < 11) {
00532 ci->levels[CA_KICKME] = ci->levels[CA_OPDEOP];
00533 ci->levels[CA_KICK] = ci->levels[CA_OPDEOP];
00534 }
00535 if (ver < 15) {
00536
00537
00538
00539
00540 ci->levels[CA_AUTOPROTECT] = ci->levels[32];
00541 ci->levels[CA_PROTECTME] = ci->levels[33];
00542 ci->levels[CA_PROTECT] = ci->levels[34];
00543
00544 ci->levels[CA_BANME] = ci->levels[CA_OPDEOP];
00545 ci->levels[CA_BAN] = ci->levels[CA_OPDEOP];
00546 ci->levels[CA_TOPIC] = ACCESS_INVALID;
00547
00548
00549 }
00550
00551 SAFE(read_int16(&ci->accesscount, f));
00552 if (ci->accesscount) {
00553 ci->access = scalloc(ci->accesscount, sizeof(ChanAccess));
00554 for (j = 0; j < ci->accesscount; j++) {
00555 SAFE(read_int16(&ci->access[j].in_use, f));
00556 if (ci->access[j].in_use) {
00557 SAFE(read_int16(&tmp16, f));
00558 ci->access[j].level = (int16) tmp16;
00559 SAFE(read_string(&s, f));
00560 if (s) {
00561 if (ver >= 13)
00562 ci->access[j].nc = findcore(s);
00563 else {
00564 na = findnick(s);
00565 if (na)
00566 ci->access[j].nc = na->nc;
00567 else
00568 ci->access[j].nc = NULL;
00569 }
00570 free(s);
00571 }
00572 if (ci->access[j].nc == NULL)
00573 ci->access[j].in_use = 0;
00574 if (ver >= 11) {
00575 SAFE(read_int32(&tmp32, f));
00576 ci->access[j].last_seen = tmp32;
00577 } else {
00578 ci->access[j].last_seen = 0;
00579 }
00580 }
00581 }
00582 } else {
00583 ci->access = NULL;
00584 }
00585
00586 SAFE(read_int16(&ci->akickcount, f));
00587 if (ci->akickcount) {
00588 ci->akick = scalloc(ci->akickcount, sizeof(AutoKick));
00589 for (j = 0; j < ci->akickcount; j++) {
00590 if (ver >= 15) {
00591 SAFE(read_int16(&ci->akick[j].flags, f));
00592 } else {
00593 SAFE(read_int16(&tmp16, f));
00594 if (tmp16)
00595 ci->akick[j].flags |= AK_USED;
00596 }
00597 if (ci->akick[j].flags & AK_USED) {
00598 if (ver < 15) {
00599 SAFE(read_int16(&tmp16, f));
00600 if (tmp16)
00601 ci->akick[j].flags |= AK_ISNICK;
00602 }
00603 SAFE(read_string(&s, f));
00604 if (ci->akick[j].flags & AK_ISNICK) {
00605 if (ver >= 13) {
00606 ci->akick[j].u.nc = findcore(s);
00607 } else {
00608 na = findnick(s);
00609 if (na)
00610 ci->akick[j].u.nc = na->nc;
00611 else
00612 ci->akick[j].u.nc = NULL;
00613 }
00614 if (!ci->akick[j].u.nc)
00615 ci->akick[j].flags &= ~AK_USED;
00616 free(s);
00617 } else {
00618 ci->akick[j].u.mask = s;
00619 }
00620 SAFE(read_string(&s, f));
00621 if (ci->akick[j].flags & AK_USED)
00622 ci->akick[j].reason = s;
00623 else if (s)
00624 free(s);
00625 if (ver >= 9) {
00626 SAFE(read_string(&s, f));
00627 if (ci->akick[j].flags & AK_USED) {
00628 ci->akick[j].creator = s;
00629 } else if (s) {
00630 free(s);
00631 }
00632 SAFE(read_int32(&tmp32, f));
00633 if (ci->akick[j].flags & AK_USED)
00634 ci->akick[j].addtime = tmp32;
00635 } else {
00636 ci->akick[j].creator = NULL;
00637 ci->akick[j].addtime = 0;
00638 }
00639 }
00640
00641
00642 if ((ver == 15) && ci->akick[j].flags > 8) {
00643 ci->akick[j].flags = 0;
00644 ci->akick[j].u.nc = NULL;
00645 ci->akick[j].u.nc = NULL;
00646 ci->akick[j].addtime = 0;
00647 ci->akick[j].creator = NULL;
00648 ci->akick[j].reason = NULL;
00649 }
00650 }
00651 } else {
00652 ci->akick = NULL;
00653 }
00654
00655 if (ver >= 10) {
00656 SAFE(read_int32(&ci->mlock_on, f));
00657 SAFE(read_int32(&ci->mlock_off, f));
00658 } else {
00659 SAFE(read_int16(&tmp16, f));
00660 ci->mlock_on = tmp16;
00661 SAFE(read_int16(&tmp16, f));
00662 ci->mlock_off = tmp16;
00663 }
00664 SAFE(read_int32(&ci->mlock_limit, f));
00665 SAFE(read_string(&ci->mlock_key, f));
00666 if (ver >= 10) {
00667 SAFE(read_string(&ci->mlock_flood, f));
00668 SAFE(read_string(&ci->mlock_redirect, f));
00669
00670
00671
00672
00673 }
00674
00675 SAFE(read_int16(&tmp16, f));
00676 ci->memos.memocount = (int16) tmp16;
00677 SAFE(read_int16(&tmp16, f));
00678 ci->memos.memomax = (int16) tmp16;
00679 if (ci->memos.memocount) {
00680 Memo *memos;
00681 memos = scalloc(sizeof(Memo) * ci->memos.memocount, 1);
00682 ci->memos.memos = memos;
00683 for (j = 0; j < ci->memos.memocount; j++, memos++) {
00684 SAFE(read_int32(&memos->number, f));
00685 SAFE(read_int16(&memos->flags, f));
00686 SAFE(read_int32(&tmp32, f));
00687 memos->time = tmp32;
00688 SAFE(read_buffer(memos->sender, f));
00689 SAFE(read_string(&memos->text, f));
00690 memos->moduleData = NULL;
00691 }
00692 }
00693
00694 SAFE(read_string(&ci->entry_message, f));
00695
00696 ci->c = NULL;
00697
00698
00699 if (ver <= 11) {
00700
00701 if (!(ci->flags & CI_VERBOTEN)
00702 && ci->successor == ci->founder) {
00703 alog("Warning: founder and successor of %s are equal. Cleaning up.", ci->name);
00704 ci->successor = NULL;
00705 }
00706 }
00707
00708
00709
00710 if (ver >= 8) {
00711 int n_ttb;
00712
00713 SAFE(read_string(&s, f));
00714 if (s) {
00715 ci->bi = findbot(s);
00716 free(s);
00717 } else
00718 ci->bi = NULL;
00719
00720 SAFE(read_int32(&tmp32, f));
00721 ci->botflags = tmp32;
00722 SAFE(read_int16(&tmp16, f));
00723 n_ttb = tmp16;
00724 ci->ttb = scalloc(2 * TTB_SIZE, 1);
00725 for (j = 0; j < n_ttb; j++) {
00726 SAFE(read_int16(&tmp16, f));
00727 if (j < TTB_SIZE)
00728 ci->ttb[j] = (int16) tmp16;
00729 }
00730 for (j = n_ttb; j < TTB_SIZE; j++)
00731 ci->ttb[j] = 0;
00732 SAFE(read_int16(&tmp16, f));
00733 ci->capsmin = tmp16;
00734 SAFE(read_int16(&tmp16, f));
00735 ci->capspercent = tmp16;
00736 SAFE(read_int16(&tmp16, f));
00737 ci->floodlines = tmp16;
00738 SAFE(read_int16(&tmp16, f));
00739 ci->floodsecs = tmp16;
00740 SAFE(read_int16(&tmp16, f));
00741 ci->repeattimes = tmp16;
00742
00743 SAFE(read_int16(&ci->bwcount, f));
00744 if (ci->bwcount) {
00745 ci->badwords = scalloc(ci->bwcount, sizeof(BadWord));
00746 for (j = 0; j < ci->bwcount; j++) {
00747 SAFE(read_int16(&ci->badwords[j].in_use, f));
00748 if (ci->badwords[j].in_use) {
00749 SAFE(read_string(&ci->badwords[j].word, f));
00750 SAFE(read_int16(&ci->badwords[j].type, f));
00751 }
00752 }
00753 } else {
00754 ci->badwords = NULL;
00755 }
00756 } else {
00757 ci->bi = NULL;
00758 ci->botflags = 0;
00759 ci->ttb = scalloc(2 * TTB_SIZE, 1);
00760 for (j = 0; j < TTB_SIZE; j++)
00761 ci->ttb[j] = 0;
00762 ci->bwcount = 0;
00763 ci->badwords = NULL;
00764 }
00765
00766 }
00767
00768 *last = NULL;
00769
00770 }
00771
00772 close_db(f);
00773
00774
00775
00776 for (i = 0; i < 256; i++) {
00777 ChannelInfo *next;
00778 for (ci = chanlists[i]; ci; ci = next) {
00779 next = ci->next;
00780 if (!(ci->flags & CI_VERBOTEN) && !ci->founder) {
00781 alog("%s: database load: Deleting founderless channel %s",
00782 s_ChanServ, ci->name);
00783 delchan(ci);
00784 continue;
00785 }
00786 if (ver < 13) {
00787 ChanAccess *access, *access2;
00788 AutoKick *akick, *akick2;
00789 int k;
00790
00791 if (ci->flags & CI_VERBOTEN)
00792 continue;
00793
00794 ci->founder->channelcount++;
00795
00796 for (j = 0, access = ci->access; j < ci->accesscount;
00797 j++, access++) {
00798 if (!access->in_use)
00799 continue;
00800 for (k = 0, access2 = ci->access; k < j;
00801 k++, access2++) {
00802 if (access2->in_use && access2->nc == access->nc) {
00803 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);
00804 memset(access, 0, sizeof(ChanAccess));
00805 break;
00806 }
00807 }
00808 }
00809 for (j = 0, akick = ci->akick; j < ci->akickcount;
00810 j++, akick++) {
00811 if (!(akick->flags & AK_USED)
00812 || !(akick->flags & AK_ISNICK))
00813 continue;
00814 for (k = 0, akick2 = ci->akick; k < j; k++, akick2++) {
00815 if ((akick2->flags & AK_USED)
00816 && (akick2->flags & AK_ISNICK)
00817 && akick2->u.nc == akick->u.nc) {
00818 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);
00819 if (akick->reason)
00820 free(akick->reason);
00821 if (akick->creator)
00822 free(akick->creator);
00823 memset(akick, 0, sizeof(AutoKick));
00824 break;
00825 }
00826 }
00827 }
00828 }
00829 }
00830 }
00831 }
00832
00833 #undef SAFE
00834
00835
00836
00837 #define SAFE(x) do { \
00838 if ((x) < 0) { \
00839 restore_db(f); \
00840 log_perror("Write error on %s", ChanDBName); \
00841 if (time(NULL) - lastwarn > WarningTimeout) { \
00842 anope_cmd_global(NULL, "Write error on %s: %s", ChanDBName, \
00843 strerror(errno)); \
00844 lastwarn = time(NULL); \
00845 } \
00846 return; \
00847 } \
00848 } while (0)
00849
00850 void save_cs_dbase(void)
00851 {
00852 dbFILE *f;
00853 int i, j;
00854 ChannelInfo *ci;
00855 Memo *memos;
00856 static time_t lastwarn = 0;
00857
00858 if (!(f = open_db(s_ChanServ, ChanDBName, "w", CHAN_VERSION)))
00859 return;
00860
00861 for (i = 0; i < 256; i++) {
00862 int16 tmp16;
00863
00864 for (ci = chanlists[i]; ci; ci = ci->next) {
00865 SAFE(write_int8(1, f));
00866 SAFE(write_buffer(ci->name, f));
00867 if (ci->founder)
00868 SAFE(write_string(ci->founder->display, f));
00869 else
00870 SAFE(write_string(NULL, f));
00871 if (ci->successor)
00872 SAFE(write_string(ci->successor->display, f));
00873 else
00874 SAFE(write_string(NULL, f));
00875 SAFE(write_buffer(ci->founderpass, f));
00876 SAFE(write_string(ci->desc, f));
00877 SAFE(write_string(ci->url, f));
00878 SAFE(write_string(ci->email, f));
00879 SAFE(write_int32(ci->time_registered, f));
00880 SAFE(write_int32(ci->last_used, f));
00881 SAFE(write_string(ci->last_topic, f));
00882 SAFE(write_buffer(ci->last_topic_setter, f));
00883 SAFE(write_int32(ci->last_topic_time, f));
00884 SAFE(write_int32(ci->flags, f));
00885 SAFE(write_string(ci->forbidby, f));
00886 SAFE(write_string(ci->forbidreason, f));
00887 SAFE(write_int16(ci->bantype, f));
00888
00889 tmp16 = CA_SIZE;
00890 SAFE(write_int16(tmp16, f));
00891 for (j = 0; j < CA_SIZE; j++)
00892 SAFE(write_int16(ci->levels[j], f));
00893
00894 SAFE(write_int16(ci->accesscount, f));
00895 for (j = 0; j < ci->accesscount; j++) {
00896 SAFE(write_int16(ci->access[j].in_use, f));
00897 if (ci->access[j].in_use) {
00898 SAFE(write_int16(ci->access[j].level, f));
00899 SAFE(write_string(ci->access[j].nc->display, f));
00900 SAFE(write_int32(ci->access[j].last_seen, f));
00901 }
00902 }
00903
00904 SAFE(write_int16(ci->akickcount, f));
00905 for (j = 0; j < ci->akickcount; j++) {
00906 SAFE(write_int16(ci->akick[j].flags, f));
00907 if (ci->akick[j].flags & AK_USED) {
00908 if (ci->akick[j].flags & AK_ISNICK)
00909 SAFE(write_string(ci->akick[j].u.nc->display, f));
00910 else
00911 SAFE(write_string(ci->akick[j].u.mask, f));
00912 SAFE(write_string(ci->akick[j].reason, f));
00913 SAFE(write_string(ci->akick[j].creator, f));
00914 SAFE(write_int32(ci->akick[j].addtime, f));
00915 }
00916 }
00917
00918 SAFE(write_int32(ci->mlock_on, f));
00919 SAFE(write_int32(ci->mlock_off, f));
00920 SAFE(write_int32(ci->mlock_limit, f));
00921 SAFE(write_string(ci->mlock_key, f));
00922 SAFE(write_string(ci->mlock_flood, f));
00923 SAFE(write_string(ci->mlock_redirect, f));
00924
00925
00926 SAFE(write_int16(ci->memos.memocount, f));
00927 SAFE(write_int16(ci->memos.memomax, f));
00928 memos = ci->memos.memos;
00929 for (j = 0; j < ci->memos.memocount; j++, memos++) {
00930 SAFE(write_int32(memos->number, f));
00931 SAFE(write_int16(memos->flags, f));
00932 SAFE(write_int32(memos->time, f));
00933 SAFE(write_buffer(memos->sender, f));
00934 SAFE(write_string(memos->text, f));
00935 }
00936
00937 SAFE(write_string(ci->entry_message, f));
00938
00939 if (ci->bi)
00940 SAFE(write_string(ci->bi->nick, f));
00941 else
00942 SAFE(write_string(NULL, f));
00943
00944 SAFE(write_int32(ci->botflags, f));
00945
00946 tmp16 = TTB_SIZE;
00947 SAFE(write_int16(tmp16, f));
00948 for (j = 0; j < TTB_SIZE; j++)
00949 SAFE(write_int16(ci->ttb[j], f));
00950
00951 SAFE(write_int16(ci->capsmin, f));
00952 SAFE(write_int16(ci->capspercent, f));
00953 SAFE(write_int16(ci->floodlines, f));
00954 SAFE(write_int16(ci->floodsecs, f));
00955 SAFE(write_int16(ci->repeattimes, f));
00956
00957 SAFE(write_int16(ci->bwcount, f));
00958 for (j = 0; j < ci->bwcount; j++) {
00959 SAFE(write_int16(ci->badwords[j].in_use, f));
00960 if (ci->badwords[j].in_use) {
00961 SAFE(write_string(ci->badwords[j].word, f));
00962 SAFE(write_int16(ci->badwords[j].type, f));
00963 }
00964 }
00965 }
00966
00967 SAFE(write_int8(0, f));
00968
00969 }
00970
00971 close_db(f);
00972
00973 }
00974
00975 #undef SAFE
00976
00977
00978
00979 void save_cs_rdb_dbase(void)
00980 {
00981 #ifdef USE_RDB
00982 int i;
00983 ChannelInfo *ci;
00984
00985 if (!rdb_open())
00986 return;
00987
00988 if (rdb_tag_table("anope_cs_info") == 0) {
00989 alog("Unable to tag table 'anope_cs_info' - ChanServ RDB save failed.");
00990 rdb_close();
00991 return;
00992 }
00993 if (rdb_tag_table("anope_cs_access") == 0) {
00994 alog("Unable to tag table 'anope_cs_access' - ChanServ RDB save failed.");
00995 rdb_close();
00996 return;
00997 }
00998 if (rdb_tag_table("anope_cs_levels") == 0) {
00999 alog("Unable to tag table 'anope_cs_levels' - ChanServ RDB save failed.");
01000 rdb_close();
01001 return;
01002 }
01003 if (rdb_tag_table("anope_cs_akicks") == 0) {
01004 alog("Unable to tag table 'anope_cs_akicks' - ChanServ RDB save failed.");
01005 rdb_close();
01006 return;
01007 }
01008 if (rdb_tag_table("anope_cs_badwords") == 0) {
01009 alog("Unable to tag table 'anope_cs_badwords' - ChanServ RDB save failed.");
01010 rdb_close();
01011 return;
01012 }
01013 if (rdb_tag_table("anope_cs_ttb") == 0) {
01014 alog("Unable to tag table 'anope_cs_ttb' - ChanServ RDB save failed.");
01015 rdb_close();
01016 return;
01017 }
01018 if (rdb_tag_table_where("anope_ms_info", "serv='CHAN'") == 0) {
01019 alog("Unable to tag table 'anope_ms_info' - ChanServ RDB save failed.");
01020 rdb_close();
01021 return;
01022 }
01023
01024 for (i = 0; i < 256; i++) {
01025 for (ci = chanlists[i]; ci; ci = ci->next) {
01026 if (rdb_save_cs_info(ci) == 0) {
01027 alog("Unable to save ChanInfo for %s - ChanServ RDB save failed.", ci->name);
01028 rdb_close();
01029 return;
01030 }
01031 }
01032 }
01033
01034 if (rdb_clean_table("anope_cs_info") == 0) {
01035 alog("Unable to clean table 'anope_cs_info' - ChanServ RDB save failed.");
01036 rdb_close();
01037 return;
01038 }
01039 if (rdb_clean_table("anope_cs_access") == 0) {
01040 alog("Unable to clean table 'anope_cs_access' - ChanServ RDB save failed.");
01041 rdb_close();
01042 return;
01043 }
01044 if (rdb_clean_table("anope_cs_levels") == 0) {
01045 alog("Unable to clean table 'anope_cs_levels' - ChanServ RDB save failed.");
01046 rdb_close();
01047 return;
01048 }
01049 if (rdb_clean_table("anope_cs_akicks") == 0) {
01050 alog("Unable to clean table 'anope_cs_akicks' - ChanServ RDB save failed.");
01051 rdb_close();
01052 return;
01053 }
01054 if (rdb_clean_table("anope_cs_badwords") == 0) {
01055 alog("Unable to clean table 'anope_cs_badwords' - ChanServ RDB save failed.");
01056 rdb_close();
01057 return;
01058 }
01059 if (rdb_clean_table("anope_cs_ttb") == 0) {
01060 alog("Unable to clean table 'anope_cs_ttb' - ChanServ RDB save failed.");
01061 rdb_close();
01062 return;
01063 }
01064 if (rdb_clean_table_where("anope_ms_info", "serv='CHAN'") == 0)
01065 alog("Unable to clean table 'anope_ms_info' - ChanServ RDB save failed.");
01066
01067 rdb_close();
01068 #endif
01069 }
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 void check_modes(Channel * c)
01082 {
01083 char modebuf[64], argbuf[BUFSIZE], *end = modebuf, *end2 = argbuf;
01084 uint32 modes = 0;
01085 ChannelInfo *ci;
01086 CBModeInfo *cbmi = NULL;
01087 CBMode *cbm = NULL;
01088 boolean DefConOn = DefConLevel != 5;
01089
01090 if (!c) {
01091 if (debug) {
01092 alog("debug: check_modes called with NULL values");
01093 }
01094 return;
01095 }
01096
01097 if (c->bouncy_modes)
01098 return;
01099
01100
01101 if (c->server_modecount >= 3 && c->chanserv_modecount >= 3) {
01102 anope_cmd_global(NULL,
01103 "Warning: unable to set modes on channel %s. "
01104 "Are your servers' U:lines configured correctly?",
01105 c->name);
01106 alog("%s: Bouncy modes on channel %s", s_ChanServ, c->name);
01107 c->bouncy_modes = 1;
01108 return;
01109 }
01110
01111 if (c->chanserv_modetime != time(NULL)) {
01112 c->chanserv_modecount = 0;
01113 c->chanserv_modetime = time(NULL);
01114 }
01115 c->chanserv_modecount++;
01116
01117
01118 if (!(ci = c->ci)) {
01119 if (ircd->regmode) {
01120 if (c->mode & ircd->regmode) {
01121 c->mode &= ~ircd->regmode;
01122 anope_cmd_mode(whosends(ci), c->name, "-r");
01123 }
01124 }
01125
01126
01127 }
01128
01129
01130
01131
01132 if (ci)
01133 modes = ~c->mode & ci->mlock_on;
01134 if (DefConOn && DefConModesSet)
01135 modes |= (~c->mode & DefConModesOn);
01136
01137
01138 *end++ = '+';
01139 cbmi = cbmodeinfos;
01140
01141 do {
01142 if (modes & cbmi->flag) {
01143 *end++ = cbmi->mode;
01144 c->mode |= cbmi->flag;
01145
01146
01147 if (cbmi->getvalue && cbmi->csgetvalue) {
01148 char *value;
01149
01150 if (DefConOn && DefConModesOn & cbmi->flag)
01151 value = cbmi->csgetvalue(&DefConModesCI);
01152 else if (ci)
01153 value = cbmi->csgetvalue(ci);
01154 else {
01155 value = NULL;
01156 if (debug)
01157 alog ("Warning: setting modes with unknown origin.");
01158 }
01159
01160 cbm = &cbmodes[(int) cbmi->mode];
01161 cbm->setvalue(c, value);
01162
01163 if (value) {
01164 *end2++ = ' ';
01165 while (*value)
01166 *end2++ = *value++;
01167 }
01168 }
01169 } else if (cbmi->getvalue && cbmi->csgetvalue
01170 && ((ci && (ci->mlock_on & cbmi->flag))
01171 || (DefConOn && DefConModesOn & cbmi->flag))
01172 && (c->mode & cbmi->flag)) {
01173 char *value = cbmi->getvalue(c);
01174 char *csvalue;
01175
01176
01177 if (DefConOn && DefConModesOn & cbmi->flag)
01178 csvalue = cbmi->csgetvalue(&DefConModesCI);
01179 else if (ci)
01180 csvalue = cbmi->csgetvalue(ci);
01181 else {
01182 csvalue = NULL;
01183 if (debug)
01184 alog ("Warning: setting modes with unknown origin.");
01185 }
01186
01187
01188 if (value && csvalue && strcmp(value, csvalue)) {
01189 *end++ = cbmi->mode;
01190
01191 cbm = &cbmodes[(int) cbmi->mode];
01192 cbm->setvalue(c, csvalue);
01193
01194 *end2++ = ' ';
01195 while (*csvalue)
01196 *end2++ = *csvalue++;
01197 }
01198 }
01199 } while ((++cbmi)->mode != 0);
01200
01201 if (*(end - 1) == '+')
01202 end--;
01203
01204 modes = 0;
01205 if (ci) {
01206 modes = c->mode & ci->mlock_off;
01207
01208 if (DefConOn && DefConModesSet)
01209 modes &= ~(modes & DefConModesOn);
01210 }
01211 if (DefConOn && DefConModesSet)
01212 modes |= c->mode & DefConModesOff;
01213
01214 if (modes) {
01215 *end++ = '-';
01216 cbmi = cbmodeinfos;
01217
01218 do {
01219 if (modes & cbmi->flag) {
01220 *end++ = cbmi->mode;
01221 c->mode &= ~cbmi->flag;
01222
01223
01224 if (cbmi->getvalue) {
01225 cbm = &cbmodes[(int) cbmi->mode];
01226
01227 if (!(cbm->flags & CBM_MINUS_NO_ARG)) {
01228 char *value = cbmi->getvalue(c);
01229
01230 if (value) {
01231 *end2++ = ' ';
01232 while (*value)
01233 *end2++ = *value++;
01234 }
01235 }
01236
01237 cbm->setvalue(c, NULL);
01238 }
01239 }
01240 } while ((++cbmi)->mode != 0);
01241 }
01242
01243 if (end == modebuf)
01244 return;
01245
01246 *end = 0;
01247 *end2 = 0;
01248
01249 anope_cmd_mode((ci ? whosends(ci) : s_OperServ), c->name, "%s%s", modebuf,
01250 (end2 == argbuf ? "" : argbuf));
01251 }
01252
01253
01254
01255 int check_valid_admin(User * user, Channel * chan, int servermode)
01256 {
01257 if (!chan || !chan->ci)
01258 return 1;
01259
01260 if (!ircd->admin) {
01261 return 0;
01262 }
01263
01264
01265 if (chan->ci->flags & CI_VERBOTEN)
01266 return 0;
01267
01268 if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT)) {
01269 notice_lang(s_ChanServ, user, CHAN_IS_REGISTERED, s_ChanServ);
01270 anope_cmd_mode(whosends(chan->ci), chan->name, "%s %s",
01271 ircd->adminunset, GET_USER(user));
01272 return 0;
01273 }
01274
01275 if (check_access(user, chan->ci, CA_AUTODEOP)) {
01276 anope_cmd_mode(whosends(chan->ci), chan->name, "%s %s",
01277 ircd->adminunset, GET_USER(user));
01278 return 0;
01279 }
01280
01281 return 1;
01282 }
01283
01284
01285
01286
01287
01288
01289
01290 int check_valid_op(User * user, Channel * chan, int servermode)
01291 {
01292 char *tmp;
01293 if (!chan || !chan->ci)
01294 return 1;
01295
01296
01297 if (chan->ci->flags & CI_VERBOTEN)
01298 return 0;
01299
01300 if (servermode && !check_access(user, chan->ci, CA_AUTOOP)) {
01301 notice_lang(s_ChanServ, user, CHAN_IS_REGISTERED, s_ChanServ);
01302 if (ircd->halfop) {
01303 if (ircd->owner && ircd->protect) {
01304 if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
01305 tmp = stripModePrefix(ircd->ownerunset);
01306 anope_cmd_mode(whosends(chan->ci), chan->name,
01307 "%so%s %s %s %s", ircd->adminunset,
01308 tmp, GET_USER(user),
01309 GET_USER(user), GET_USER(user));
01310 free(tmp);
01311 } else {
01312 tmp = stripModePrefix(ircd->ownerunset);
01313 anope_cmd_mode(whosends(chan->ci), chan->name,
01314 "%sho%s %s %s %s %s",
01315 ircd->adminunset, tmp,
01316 GET_USER(user), GET_USER(user), GET_USER(user),
01317 GET_USER(user));
01318 free(tmp);
01319 }
01320 } else if (!ircd->owner && ircd->protect) {
01321 if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
01322 anope_cmd_mode(whosends(chan->ci), chan->name,
01323 "%so %s %s", ircd->adminunset,
01324 GET_USER(user), GET_USER(user));
01325 } else {
01326 anope_cmd_mode(whosends(chan->ci), chan->name,
01327 "%soh %s %s %s", ircd->adminunset,
01328 GET_USER(user), GET_USER(user), GET_USER(user));
01329 }
01330 } else {
01331 if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
01332 anope_cmd_mode(whosends(chan->ci), chan->name, "-o %s",
01333 GET_USER(user));
01334 } else {
01335 anope_cmd_mode(whosends(chan->ci), chan->name,
01336 "-ho %s %s", GET_USER(user), GET_USER(user));
01337 }
01338 }
01339 } else {
01340 anope_cmd_mode(whosends(chan->ci), chan->name, "-o %s",
01341 GET_USER(user));
01342 }
01343 return 0;
01344 }
01345
01346 if (check_access(user, chan->ci, CA_AUTODEOP)) {
01347 if (ircd->halfop) {
01348 if (ircd->owner && ircd->protect) {
01349 tmp = stripModePrefix(ircd->ownerunset);
01350 anope_cmd_mode(whosends(chan->ci), chan->name,
01351 "%sho%s %s %s %s %s", ircd->adminunset,
01352 tmp, GET_USER(user), GET_USER(user),
01353 GET_USER(user), GET_USER(user));
01354 free(tmp);
01355 } else {
01356 anope_cmd_mode(whosends(chan->ci), chan->name, "-ho %s %s",
01357 GET_USER(user), GET_USER(user));
01358 }
01359 } else {
01360 anope_cmd_mode(whosends(chan->ci), chan->name, "-o %s",
01361 GET_USER(user));
01362 }
01363 return 0;
01364 }
01365
01366 return 1;
01367 }
01368
01369
01370
01371
01372
01373
01374
01375 int check_should_op(User * user, char *chan)
01376 {
01377 ChannelInfo *ci = cs_findchan(chan);
01378
01379 if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
01380 return 0;
01381
01382 if ((ci->flags & CI_SECURE) && !nick_identified(user))
01383 return 0;
01384
01385 if (check_access(user, ci, CA_AUTOOP)) {
01386 anope_cmd_mode(whosends(ci), chan, "+o %s", GET_USER(user));
01387 return 1;
01388 }
01389
01390 return 0;
01391 }
01392
01393
01394
01395
01396
01397
01398 int check_should_voice(User * user, char *chan)
01399 {
01400 ChannelInfo *ci = cs_findchan(chan);
01401
01402 if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
01403 return 0;
01404
01405 if ((ci->flags & CI_SECURE) && !nick_identified(user))
01406 return 0;
01407
01408 if (check_access(user, ci, CA_AUTOVOICE)) {
01409 anope_cmd_mode(whosends(ci), chan, "+v %s", GET_USER(user));
01410 return 1;
01411 }
01412
01413 return 0;
01414 }
01415
01416
01417
01418 int check_should_halfop(User * user, char *chan)
01419 {
01420 ChannelInfo *ci = cs_findchan(chan);
01421
01422 if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
01423 return 0;
01424
01425 if (check_access(user, ci, CA_AUTOHALFOP)) {
01426 anope_cmd_mode(whosends(ci), chan, "+h %s", GET_USER(user));
01427 return 1;
01428 }
01429
01430 return 0;
01431 }
01432
01433
01434
01435 int check_should_owner(User * user, char *chan)
01436 {
01437 char *tmp;
01438 ChannelInfo *ci = cs_findchan(chan);
01439
01440 if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
01441 return 0;
01442
01443 if (((ci->flags & CI_SECUREFOUNDER) && is_real_founder(user, ci))
01444 || (!(ci->flags & CI_SECUREFOUNDER) && is_founder(user, ci))) {
01445 tmp = stripModePrefix(ircd->ownerset);
01446 anope_cmd_mode(whosends(ci), chan, "+o%s %s %s", tmp, GET_USER(user),
01447 GET_USER(user));
01448 free(tmp);
01449 return 1;
01450 }
01451
01452 return 0;
01453 }
01454
01455
01456
01457 int check_should_protect(User * user, char *chan)
01458 {
01459 char *tmp;
01460 ChannelInfo *ci = cs_findchan(chan);
01461
01462 if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
01463 return 0;
01464
01465 if (check_access(user, ci, CA_AUTOPROTECT)) {
01466 tmp = stripModePrefix(ircd->adminset);
01467 anope_cmd_mode(whosends(ci), chan, "+o%s %s %s", tmp, GET_USER(user),
01468 GET_USER(user));
01469 free(tmp);
01470 return 1;
01471 }
01472
01473 return 0;
01474 }
01475
01476
01477
01478
01479
01480 static void timeout_leave(Timeout * to)
01481 {
01482 char *chan = to->data;
01483 ChannelInfo *ci = cs_findchan(chan);
01484
01485 if (ci)
01486 ci->flags &= ~CI_INHABIT;
01487
01488 anope_cmd_part(s_ChanServ, chan, NULL);
01489 free(to->data);
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 int check_kick(User * user, char *chan, time_t chants)
01501 {
01502 ChannelInfo *ci = cs_findchan(chan);
01503 Channel *c;
01504 AutoKick *akick;
01505 int i, set_modes = 0;
01506 NickCore *nc;
01507 char *av[4];
01508 int ac;
01509 char buf[BUFSIZE];
01510 char mask[BUFSIZE];
01511 const char *reason;
01512 Timeout *t;
01513
01514 if (!ci)
01515 return 0;
01516
01517 if (user->isSuperAdmin == 1)
01518 return 0;
01519
01520
01521
01522 if (is_ulined(user->server->name)) {
01523 return 0;
01524 }
01525
01526 if (ci->flags & CI_VERBOTEN) {
01527 get_idealban(ci, user, mask, sizeof(mask));
01528 reason =
01529 ci->forbidreason ? ci->forbidreason : getstring(user->na,
01530 CHAN_MAY_NOT_BE_USED);
01531 set_modes = 1;
01532 goto kick;
01533 }
01534
01535 if (ci->flags & CI_SUSPENDED) {
01536 get_idealban(ci, user, mask, sizeof(mask));
01537 reason =
01538 ci->forbidreason ? ci->forbidreason : getstring(user->na,
01539 CHAN_MAY_NOT_BE_USED);
01540 set_modes = 1;
01541 goto kick;
01542 }
01543
01544 if (nick_recognized(user))
01545 nc = user->na->nc;
01546 else
01547 nc = NULL;
01548
01549
01550
01551
01552
01553
01554
01555
01556 if (ircd->except && is_excepted(ci, user) == 1) {
01557 return 0;
01558 }
01559
01560 for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
01561 if (!(akick->flags & AK_USED))
01562 continue;
01563 if ((akick->flags & AK_ISNICK && akick->u.nc == nc)
01564 || (!(akick->flags & AK_ISNICK)
01565 && match_usermask(akick->u.mask, user))) {
01566 if (debug >= 2)
01567 alog("debug: %s matched akick %s", user->nick,
01568 (akick->flags & AK_ISNICK) ? akick->u.nc->
01569 display : akick->u.mask);
01570 if (akick->flags & AK_ISNICK)
01571 get_idealban(ci, user, mask, sizeof(mask));
01572 else
01573 strscpy(mask, akick->u.mask, sizeof(mask));
01574 reason = akick->reason ? akick->reason : CSAutokickReason;
01575 goto kick;
01576 }
01577 }
01578
01579 if (check_access(user, ci, CA_NOJOIN)) {
01580 get_idealban(ci, user, mask, sizeof(mask));
01581 reason = getstring(user->na, CHAN_NOT_ALLOWED_TO_JOIN);
01582 goto kick;
01583 }
01584
01585 return 0;
01586
01587 kick:
01588 if (debug)
01589 alog("debug: channel: AutoKicking %s!%s@%s from %s", user->nick,
01590 user->username, user->host, chan);
01591
01592
01593
01594
01595
01596
01597
01598 if ((!(c = findchan(chan)) || c->usercount == 0)
01599 && !(ci->flags & CI_INHABIT)) {
01600 anope_cmd_join(s_ChanServ, chan, (c ? c->creation_time : chants));
01601
01602
01603
01604
01605 if (set_modes)
01606 anope_cmd_mode(s_ChanServ, chan, "+ntsi");
01607 t = add_timeout(CSInhabit, timeout_leave, 0);
01608 t->data = sstrdup(chan);
01609 ci->flags |= CI_INHABIT;
01610 }
01611
01612 if (c) {
01613 if (ircdcap->tsmode) {
01614 snprintf(buf, BUFSIZE - 1, "%ld", (long int) time(NULL));
01615 av[0] = chan;
01616 av[1] = buf;
01617 av[2] = sstrdup("+b");
01618 av[3] = mask;
01619 ac = 4;
01620 } else {
01621 av[0] = chan;
01622 av[1] = sstrdup("+b");
01623 av[2] = mask;
01624 ac = 3;
01625 }
01626
01627 do_cmode(whosends(ci), ac, av);
01628
01629 if (ircdcap->tsmode)
01630 free(av[2]);
01631 else
01632 free(av[1]);
01633 }
01634
01635 anope_cmd_mode(whosends(ci), chan, "+b %s", mask);
01636 anope_cmd_kick(whosends(ci), chan, user->nick, "%s", reason);
01637
01638 return 1;
01639 }
01640
01641
01642
01643
01644
01645 void record_topic(const char *chan)
01646 {
01647 Channel *c;
01648 ChannelInfo *ci;
01649
01650 if (readonly)
01651 return;
01652
01653 c = findchan(chan);
01654 if (!c || !(ci = c->ci))
01655 return;
01656
01657 if (ci->last_topic)
01658 free(ci->last_topic);
01659
01660 if (c->topic)
01661 ci->last_topic = sstrdup(c->topic);
01662 else
01663 ci->last_topic = NULL;
01664
01665 strscpy(ci->last_topic_setter, c->topic_setter, NICKMAX);
01666 ci->last_topic_time = c->topic_time;
01667 }
01668
01669
01670
01671
01672
01673 void restore_topic(char *chan)
01674 {
01675 Channel *c = findchan(chan);
01676 ChannelInfo *ci;
01677
01678 if (!c || !(ci = c->ci))
01679 return;
01680
01681 c->topic_sync = 1;
01682 if (!(ci->flags & CI_KEEPTOPIC)) {
01683
01684
01685
01686 ci->last_topic = NULL;
01687 strscpy(ci->last_topic_setter, whosends(ci), NICKMAX);
01688 ci->last_topic_time = time(NULL);
01689 return;
01690 }
01691 if (c->topic)
01692 free(c->topic);
01693 if (ci->last_topic) {
01694 c->topic = sstrdup(ci->last_topic);
01695 strscpy(c->topic_setter, ci->last_topic_setter, NICKMAX);
01696 c->topic_time = ci->last_topic_time;
01697 } else {
01698 c->topic = NULL;
01699 strscpy(c->topic_setter, whosends(ci), NICKMAX);
01700 }
01701 if (ircd->join2set) {
01702 if (whosends(ci) == s_ChanServ) {
01703 anope_cmd_join(s_ChanServ, chan, c->creation_time);
01704 anope_cmd_mode(NULL, chan, "+o %s", GET_BOT(s_ChanServ));
01705 }
01706 }
01707 anope_cmd_topic(whosends(ci), c->name, c->topic_setter,
01708 c->topic ? c->topic : "", c->topic_time);
01709 if (ircd->join2set) {
01710 if (whosends(ci) == s_ChanServ) {
01711 anope_cmd_part(s_ChanServ, c->name, NULL);
01712 }
01713 }
01714 }
01715
01716
01717
01718
01719
01720
01721 int check_topiclock(Channel * c, time_t topic_time)
01722 {
01723 ChannelInfo *ci;
01724
01725 if (!c) {
01726 if (debug) {
01727 alog("debug: check_topiclock called with NULL values");
01728 }
01729 return 0;
01730 }
01731
01732 if (!(ci = c->ci) || !(ci->flags & CI_TOPICLOCK))
01733 return 0;
01734
01735 if (c->topic)
01736 free(c->topic);
01737 if (ci->last_topic) {
01738 c->topic = sstrdup(ci->last_topic);
01739 strscpy(c->topic_setter, ci->last_topic_setter, NICKMAX);
01740 } else {
01741 c->topic = NULL;
01742
01743
01744 strscpy(c->topic_setter, whosends(ci), NICKMAX);
01745 }
01746
01747 if (ircd->topictsforward) {
01748
01749
01750 if (!topic_time) {
01751 c->topic_time = time(NULL) + 1;
01752 } else {
01753 c->topic_time = topic_time + 1;
01754 }
01755 } else {
01756
01757 if (ci->last_topic)
01758 c->topic_time = ci->last_topic_time;
01759 else
01760 c->topic_time = time(NULL) + 1;
01761 }
01762
01763 if (ircd->join2set) {
01764 if (whosends(ci) == s_ChanServ) {
01765 anope_cmd_join(s_ChanServ, c->name, c->creation_time);
01766 anope_cmd_mode(NULL, c->name, "+o %s", GET_BOT(s_ChanServ));
01767 }
01768 }
01769
01770 anope_cmd_topic(whosends(ci), c->name, c->topic_setter,
01771 c->topic ? c->topic : "", c->topic_time);
01772
01773 if (ircd->join2set) {
01774 if (whosends(ci) == s_ChanServ) {
01775 anope_cmd_part(s_ChanServ, c->ci->name, NULL);
01776 }
01777 }
01778 return 1;
01779 }
01780
01781
01782
01783
01784
01785 void expire_chans()
01786 {
01787 ChannelInfo *ci, *next;
01788 int i;
01789 time_t now = time(NULL);
01790
01791 if (!CSExpire)
01792 return;
01793
01794 for (i = 0; i < 256; i++) {
01795 for (ci = chanlists[i]; ci; ci = next) {
01796 next = ci->next;
01797 if (!ci->c && now - ci->last_used >= CSExpire
01798 && !(ci->
01799 flags & (CI_VERBOTEN | CI_NO_EXPIRE | CI_SUSPENDED)))
01800 {
01801 send_event(EVENT_CHAN_EXPIRE, 1, ci->name);
01802 alog("Expiring channel %s (founder: %s)", ci->name,
01803 (ci->founder ? ci->founder->display : "(none)"));
01804 delchan(ci);
01805 }
01806 }
01807 }
01808 }
01809
01810
01811
01812
01813
01814 void cs_remove_nick(const NickCore * nc)
01815 {
01816 int i, j, k;
01817 ChannelInfo *ci, *next;
01818 ChanAccess *ca;
01819 AutoKick *akick;
01820
01821 for (i = 0; i < 256; i++) {
01822 for (ci = chanlists[i]; ci; ci = next) {
01823 next = ci->next;
01824 if (ci->founder == nc) {
01825 if (ci->successor) {
01826 NickCore *nc2 = ci->successor;
01827 if (!nick_is_services_admin(nc2) && nc2->channelmax > 0
01828 && nc2->channelcount >= nc2->channelmax) {
01829 alog("%s: Successor (%s) of %s owns too many channels, " "deleting channel", s_ChanServ, nc2->display, ci->name);
01830 delchan(ci);
01831 continue;
01832 } else {
01833 alog("%s: Transferring foundership of %s from deleted " "nick %s to successor %s", s_ChanServ, ci->name, nc->display, nc2->display);
01834 ci->founder = nc2;
01835 ci->successor = NULL;
01836 nc2->channelcount++;
01837 }
01838 } else {
01839 alog("%s: Deleting channel %s owned by deleted nick %s", s_ChanServ, ci->name, nc->display);
01840 if (ircd->regmode) {
01841
01842 if ((ci->c) && (ci->c->mode & ircd->regmode)) {
01843 ci->c->mode &= ~ircd->regmode;
01844 anope_cmd_mode(whosends(ci), ci->name, "-r");
01845 }
01846 }
01847
01848 delchan(ci);
01849 continue;
01850 }
01851 }
01852
01853 if (ci->successor == nc)
01854 ci->successor = NULL;
01855
01856 for (ca = ci->access, j = ci->accesscount; j > 0; ca++, j--) {
01857 if (ca->in_use && ca->nc == nc) {
01858 ca->in_use = 0;
01859 ca->nc = NULL;
01860 }
01861 }
01862 CleanAccess(ci);
01863
01864 for (akick = ci->akick, j = 0; j < ci->akickcount; akick++, j++) {
01865 if ((akick->flags & AK_USED) && (akick->flags & AK_ISNICK)
01866 && akick->u.nc == nc) {
01867 if (akick->creator) {
01868 free(akick->creator);
01869 akick->creator = NULL;
01870 }
01871 if (akick->reason) {
01872 free(akick->reason);
01873 akick->reason = NULL;
01874 }
01875 akick->flags = 0;
01876 akick->addtime = 0;
01877 akick->u.nc = NULL;
01878
01879
01880 break;
01881 }
01882 }
01883
01884
01885
01886 if (j < ci->akickcount - 1) {
01887 for (k = j + 1; k < ci->akickcount; j++, k++) {
01888 if (ci->akick[k].flags & AK_USED) {
01889
01890 if (ci->akick[k].flags & AK_ISNICK) {
01891 ci->akick[j].u.nc = ci->akick[k].u.nc;
01892 ci->akick[k].u.nc = NULL;
01893 } else {
01894 ci->akick[j].u.mask = sstrdup(ci->akick[k].u.mask);
01895 free(ci->akick[k].u.mask);
01896 ci->akick[k].u.mask = NULL;
01897 }
01898
01899 if (ci->akick[k].reason) {
01900 ci->akick[j].reason = sstrdup(ci->akick[k].reason);
01901 free(ci->akick[k].reason);
01902 ci->akick[k].reason = NULL;
01903 } else
01904 ci->akick[j].reason = NULL;
01905
01906 ci->akick[j].creator = sstrdup(ci->akick[k].creator);
01907 free(ci->akick[k].creator);
01908 ci->akick[k].creator = NULL;
01909
01910 ci->akick[j].flags = ci->akick[k].flags;
01911 ci->akick[k].flags = 0;
01912
01913 ci->akick[j].addtime = ci->akick[k].addtime;
01914 ci->akick[k].addtime = 0;
01915 }
01916 }
01917 }
01918
01919
01920
01921 ci->akickcount = j;
01922 ci->akick = srealloc(ci->akick,sizeof(AutoKick) * ci->akickcount);
01923 }
01924 }
01925 }
01926
01927
01928
01929
01930
01931 void cs_remove_bot(const BotInfo * bi)
01932 {
01933 int i;
01934 ChannelInfo *ci;
01935
01936 for (i = 0; i < 256; i++)
01937 for (ci = chanlists[i]; ci; ci = ci->next)
01938 if (ci->bi == bi)
01939 ci->bi = NULL;
01940 }
01941
01942
01943
01944
01945
01946
01947 ChannelInfo *cs_findchan(const char *chan)
01948 {
01949 ChannelInfo *ci;
01950
01951 if (!chan || !*chan) {
01952 if (debug) {
01953 alog("debug: cs_findchan() called with NULL values");
01954 }
01955 return NULL;
01956 }
01957
01958 for (ci = chanlists[(unsigned char) tolower(chan[1])]; ci;
01959 ci = ci->next) {
01960 if (stricmp(ci->name, chan) == 0)
01961 return ci;
01962 }
01963 return NULL;
01964 }
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974 int check_access(User * user, ChannelInfo * ci, int what)
01975 {
01976 int level;
01977 int limit;
01978
01979 if (!user || !ci) {
01980 return 0;
01981 }
01982
01983 level = get_access(user, ci);
01984 limit = ci->levels[what];
01985
01986
01987 if (level > 0)
01988 ci->last_used = time(NULL);
01989
01990 if (level >= ACCESS_FOUNDER)
01991 return (what == CA_AUTODEOP || what == CA_NOJOIN) ? 0 : 1;
01992
01993 if (what == CA_AUTODEOP && (ci->flags & CI_SECUREOPS) && level == 0)
01994 return 1;
01995 if (limit == ACCESS_INVALID)
01996 return 0;
01997 if (what == CA_AUTODEOP || what == CA_NOJOIN)
01998 return level <= ci->levels[what];
01999 else
02000 return level >= ci->levels[what];
02001 }
02002
02003
02004
02005
02006
02007
02008
02009 void alpha_insert_chan(ChannelInfo * ci)
02010 {
02011 ChannelInfo *ptr, *prev;
02012 char *chan;
02013
02014 if (!ci) {
02015 if (debug) {
02016 alog("debug: alpha_insert_chan called with NULL values");
02017 }
02018 return;
02019 }
02020
02021 chan = ci->name;
02022
02023 for (prev = NULL, ptr = chanlists[(unsigned char) tolower(chan[1])];
02024 ptr != NULL && stricmp(ptr->name, chan) < 0;
02025 prev = ptr, ptr = ptr->next);
02026 ci->prev = prev;
02027 ci->next = ptr;
02028 if (!prev)
02029 chanlists[(unsigned char) tolower(chan[1])] = ci;
02030 else
02031 prev->next = ci;
02032 if (ptr)
02033 ptr->prev = ci;
02034 }
02035
02036
02037
02038
02039
02040
02041
02042 ChannelInfo *makechan(const char *chan)
02043 {
02044 int i;
02045 ChannelInfo *ci;
02046
02047 ci = scalloc(sizeof(ChannelInfo), 1);
02048 strscpy(ci->name, chan, CHANMAX);
02049 ci->time_registered = time(NULL);
02050 reset_levels(ci);
02051 ci->ttb = scalloc(2 * TTB_SIZE, 1);
02052 for (i = 0; i < TTB_SIZE; i++)
02053 ci->ttb[i] = 0;
02054 alpha_insert_chan(ci);
02055 return ci;
02056 }
02057
02058
02059
02060
02061
02062
02063 int delchan(ChannelInfo * ci)
02064 {
02065 int i;
02066 NickCore *nc;
02067 User *u;
02068 struct u_chaninfolist *cilist, *cilist_next;
02069
02070 if (!ci) {
02071 if (debug) {
02072 alog("debug: delchan called with NULL values");
02073 }
02074 return 0;
02075 }
02076
02077 nc = ci->founder;
02078
02079 if (debug >= 2) {
02080 alog("debug: delchan removing %s", ci->name);
02081 }
02082
02083 if (ci->bi) {
02084 ci->bi->chancount--;
02085 }
02086
02087 if (debug >= 2) {
02088 alog("debug: delchan top of removing the bot");
02089 }
02090 if (ci->c) {
02091 if (ci->bi && ci->c->usercount >= BSMinUsers) {
02092 anope_cmd_part(ci->bi->nick, ci->c->name, NULL);
02093 }
02094 ci->c->ci = NULL;
02095 }
02096 if (debug >= 2) {
02097 alog("debug: delchan() Bot has been removed moving on");
02098 }
02099
02100 if (debug >= 2) {
02101 alog("debug: delchan() founder cleanup");
02102 }
02103 for (i = 0; i < 1024; i++) {
02104 for (u = userlist[i]; u; u = u->next) {
02105 cilist = u->founder_chans;
02106 while (cilist) {
02107 cilist_next = cilist->next;
02108 if (cilist->chan == ci) {
02109 if (debug)
02110 alog("debug: Dropping founder login of %s for %s",
02111 u->nick, ci->name);
02112 if (cilist->next)
02113 cilist->next->prev = cilist->prev;
02114 if (cilist->prev)
02115 cilist->prev->next = cilist->next;
02116 else
02117 u->founder_chans = cilist->next;
02118 free(cilist);
02119 }
02120 cilist = cilist_next;
02121 }
02122 }
02123 }
02124 if (debug >= 2) {
02125 alog("debug: delchan() founder cleanup done");
02126 }
02127
02128 if (ci->next)
02129 ci->next->prev = ci->prev;
02130 if (ci->prev)
02131 ci->prev->next = ci->next;
02132 else
02133 chanlists[(unsigned char) tolower(ci->name[1])] = ci->next;
02134 if (ci->desc)
02135 free(ci->desc);
02136 if (ci->url)
02137 free(ci->url);
02138 if (ci->email)
02139 free(ci->email);
02140 if (ci->entry_message)
02141 free(ci->entry_message);
02142
02143 if (ci->mlock_key)
02144 free(ci->mlock_key);
02145 if (ircd->fmode) {
02146 if (ci->mlock_flood)
02147 free(ci->mlock_flood);
02148 }
02149 if (ircd->Lmode) {
02150 if (ci->mlock_redirect)
02151 free(ci->mlock_redirect);
02152 }
02153 if (ircd->jmode) {
02154 if (ci->mlock_throttle)
02155 free(ci->mlock_throttle);
02156 }
02157 if (ci->last_topic)
02158 free(ci->last_topic);
02159 if (ci->forbidby)
02160 free(ci->forbidby);
02161 if (ci->forbidreason)
02162 free(ci->forbidreason);
02163 if (ci->access)
02164 free(ci->access);
02165 if (debug >= 2) {
02166 alog("debug: delchan() top of the akick list");
02167 }
02168 for (i = 0; i < ci->akickcount; i++) {
02169 if (!(ci->akick[i].flags & AK_ISNICK) && ci->akick[i].u.mask)
02170 free(ci->akick[i].u.mask);
02171 if (ci->akick[i].reason)
02172 free(ci->akick[i].reason);
02173 if (ci->akick[i].creator)
02174 free(ci->akick[i].creator);
02175 }
02176 if (debug >= 2) {
02177 alog("debug: delchan() done with the akick list");
02178 }
02179 if (ci->akick)
02180 free(ci->akick);
02181 if (ci->levels)
02182 free(ci->levels);
02183 if (debug >= 2) {
02184 alog("debug: delchan() top of the memo list");
02185 }
02186 if (ci->memos.memos) {
02187 for (i = 0; i < ci->memos.memocount; i++) {
02188 if (ci->memos.memos[i].text)
02189 free(ci->memos.memos[i].text);
02190 moduleCleanStruct(&ci->memos.memos[i].moduleData);
02191 }
02192 free(ci->memos.memos);
02193 }
02194 if (debug >= 2) {
02195 alog("debug: delchan() done with the memo list");
02196 }
02197 if (ci->ttb)
02198 free(ci->ttb);
02199
02200 if (debug >= 2) {
02201 alog("debug: delchan() top of the badword list");
02202 }
02203 for (i = 0; i < ci->bwcount; i++) {
02204 if (ci->badwords[i].word)
02205 free(ci->badwords[i].word);
02206 }
02207 if (ci->badwords)
02208 free(ci->badwords);
02209 if (debug >= 2) {
02210 alog("debug: delchan() done with the badword list");
02211 }
02212
02213
02214 if (debug >= 2) {
02215 alog("debug: delchan() calling on moduleCleanStruct()");
02216 }
02217 moduleCleanStruct(&ci->moduleData);
02218
02219 free(ci);
02220 if (nc)
02221 nc->channelcount--;
02222
02223 if (debug >= 2) {
02224 alog("debug: delchan() all done");
02225 }
02226 return 1;
02227 }
02228
02229
02230
02231
02232
02233 void reset_levels(ChannelInfo * ci)
02234 {
02235 int i;
02236
02237 if (!ci) {
02238 if (debug) {
02239 alog("debug: reset_levels called with NULL values");
02240 }
02241 return;
02242 }
02243
02244 if (ci->levels)
02245 free(ci->levels);
02246 ci->levels = scalloc(CA_SIZE * sizeof(*ci->levels), 1);
02247 for (i = 0; def_levels[i][0] >= 0; i++)
02248 ci->levels[def_levels[i][0]] = def_levels[i][1];
02249 }
02250
02251
02252
02253
02254
02255 int is_founder(User * user, ChannelInfo * ci)
02256 {
02257 if (!user || !ci) {
02258 return 0;
02259 }
02260
02261 if (user->isSuperAdmin) {
02262 return 1;
02263 }
02264
02265 if (user->na && user->na->nc == ci->founder) {
02266 if ((nick_identified(user)
02267 || (nick_recognized(user) && !(ci->flags & CI_SECURE))))
02268 return 1;
02269 }
02270 if (is_identified(user, ci))
02271 return 1;
02272 return 0;
02273 }
02274
02275
02276
02277 int is_real_founder(User * user, ChannelInfo * ci)
02278 {
02279 if (user->isSuperAdmin) {
02280 return 1;
02281 }
02282
02283 if (user->na && user->na->nc == ci->founder) {
02284 if ((nick_identified(user)
02285 || (nick_recognized(user) && !(ci->flags & CI_SECURE))))
02286 return 1;
02287 }
02288 return 0;
02289 }
02290
02291
02292
02293
02294
02295 int is_identified(User * user, ChannelInfo * ci)
02296 {
02297 struct u_chaninfolist *c;
02298
02299 for (c = user->founder_chans; c; c = c->next) {
02300 if (c->chan == ci)
02301 return 1;
02302 }
02303 return 0;
02304 }
02305
02306
02307
02308
02309
02310 ChanAccess *get_access_entry(NickCore * nc, ChannelInfo * ci)
02311 {
02312 ChanAccess *access;
02313 int i;
02314
02315 if (!ci || !nc) {
02316 return NULL;
02317 }
02318
02319 for (access = ci->access, i = 0; i < ci->accesscount; access++, i++)
02320 if (access->in_use && access->nc == nc)
02321 return access;
02322
02323 return NULL;
02324 }
02325
02326
02327
02328
02329
02330
02331
02332 int get_access(User * user, ChannelInfo * ci)
02333 {
02334 ChanAccess *access;
02335
02336 if (!ci || !user)
02337 return 0;
02338
02339
02340 if (user->isSuperAdmin)
02341 return ACCESS_SUPERADMIN;
02342
02343 if (is_founder(user, ci))
02344 return ACCESS_FOUNDER;
02345
02346 if (!user->na)
02347 return 0;
02348
02349 if (nick_identified(user)
02350 || (nick_recognized(user) && !(ci->flags & CI_SECURE)))
02351 if ((access = get_access_entry(user->na->nc, ci)))
02352 return access->level;
02353
02354 if (nick_identified(user))
02355 return 0;
02356
02357 return 0;
02358 }
02359
02360
02361
02362 void update_cs_lastseen(User * user, ChannelInfo * ci)
02363 {
02364 ChanAccess *access;
02365
02366 if (!ci || !user || !user->na)
02367 return;
02368
02369 if (is_founder(user, ci) || nick_identified(user)
02370 || (nick_recognized(user) && !(ci->flags & CI_SECURE)))
02371 if ((access = get_access_entry(user->na->nc, ci)))
02372 access->last_seen = time(NULL);
02373 }
02374
02375
02376
02377
02378
02379
02380 int get_idealban(ChannelInfo * ci, User * u, char *ret, int retlen)
02381 {
02382 char *mask;
02383
02384 if (!ci || !u || !ret || retlen == 0)
02385 return 0;
02386
02387 switch (ci->bantype) {
02388 case 0:
02389 snprintf(ret, retlen, "*!%s@%s", common_get_vident(u),
02390 common_get_vhost(u));
02391 return 1;
02392 case 1:
02393 snprintf(ret, retlen, "*!%s%s@%s",
02394 (strlen(common_get_vident(u)) <
02395 (*(common_get_vident(u)) ==
02396 '~' ? USERMAX + 1 : USERMAX) ? "*" : ""),
02397 (*(common_get_vident(u)) ==
02398 '~' ? common_get_vident(u) + 1 : common_get_vident(u)),
02399 common_get_vhost(u));
02400 return 1;
02401 case 2:
02402 snprintf(ret, retlen, "*!*@%s", common_get_vhost(u));
02403 return 1;
02404 case 3:
02405 mask = create_mask(u);
02406 snprintf(ret, retlen, "*!%s", mask);
02407 free(mask);
02408 return 1;
02409
02410 default:
02411 return 0;
02412 }
02413 }
02414
02415
02416
02417 char *cs_get_flood(ChannelInfo * ci)
02418 {
02419 if (!ci) {
02420 return NULL;
02421 } else {
02422 if (ircd->fmode) {
02423 return ci->mlock_flood;
02424 } else {
02425 return NULL;
02426 }
02427 }
02428 }
02429
02430
02431
02432 char *cs_get_throttle(ChannelInfo * ci)
02433 {
02434 if (!ci) {
02435 return NULL;
02436 } else {
02437 if (ircd->jmode) {
02438 return ci->mlock_throttle;
02439 } else {
02440 return NULL;
02441 }
02442 }
02443 }
02444
02445
02446
02447 char *cs_get_key(ChannelInfo * ci)
02448 {
02449 if (!ci) {
02450 return NULL;
02451 } else {
02452 return ci->mlock_key;
02453 }
02454 }
02455
02456
02457
02458 char *cs_get_limit(ChannelInfo * ci)
02459 {
02460 static char limit[16];
02461
02462 if (!ci) {
02463 return NULL;
02464 }
02465
02466 if (ci->mlock_limit == 0)
02467 return NULL;
02468
02469 snprintf(limit, sizeof(limit), "%lu",
02470 (unsigned long int) ci->mlock_limit);
02471 return limit;
02472 }
02473
02474
02475
02476 char *cs_get_redirect(ChannelInfo * ci)
02477 {
02478 if (!ci) {
02479 return NULL;
02480 } else {
02481 if (ircd->Lmode) {
02482 return ci->mlock_redirect;
02483 } else {
02484 return NULL;
02485 }
02486 }
02487 }
02488
02489
02490
02491
02492
02493 char *cs_get_unkwn(ChannelInfo * ci)
02494 {
02495 return NULL;
02496 }
02497
02498
02499
02500 void cs_set_flood(ChannelInfo * ci, char *value)
02501 {
02502 if (!ci) {
02503 return;
02504 }
02505
02506 if (ci->mlock_flood)
02507 free(ci->mlock_flood);
02508
02509
02510 if (anope_flood_mode_check(value)) {
02511 ci->mlock_flood = sstrdup(value);
02512 } else {
02513 ci->mlock_on &= ~ircd->chan_fmode;
02514 ci->mlock_flood = NULL;
02515 }
02516 }
02517
02518
02519
02520 void cs_set_throttle(ChannelInfo * ci, char *value)
02521 {
02522 if (!ci)
02523 return;
02524
02525 if (ci->mlock_throttle)
02526 free(ci->mlock_throttle);
02527
02528 if (anope_jointhrottle_mode_check(value)) {
02529 ci->mlock_throttle = sstrdup(value);
02530 } else {
02531 ci->mlock_on &= ~ircd->chan_jmode;
02532 ci->mlock_throttle = NULL;
02533 }
02534 }
02535
02536
02537
02538 void cs_set_key(ChannelInfo * ci, char *value)
02539 {
02540 if (!ci) {
02541 return;
02542 }
02543
02544 if (ci->mlock_key)
02545 free(ci->mlock_key);
02546
02547
02548 if (value && *value != ':' && !strchr(value, ',')) {
02549 ci->mlock_key = sstrdup(value);
02550 } else {
02551 ci->mlock_on &= ~anope_get_key_mode();
02552 ci->mlock_key = NULL;
02553 }
02554 }
02555
02556
02557
02558 void cs_set_limit(ChannelInfo * ci, char *value)
02559 {
02560 if (!ci) {
02561 return;
02562 }
02563
02564 ci->mlock_limit = value ? strtoul(value, NULL, 10) : 0;
02565
02566 if (ci->mlock_limit <= 0)
02567 ci->mlock_on &= ~anope_get_limit_mode();
02568 }
02569
02570
02571
02572 void cs_set_redirect(ChannelInfo * ci, char *value)
02573 {
02574 if (!ci) {
02575 return;
02576 }
02577
02578 if (ci->mlock_redirect)
02579 free(ci->mlock_redirect);
02580
02581
02582 if (value && *value == '#') {
02583 ci->mlock_redirect = sstrdup(value);
02584 } else {
02585 ci->mlock_on &= ~ircd->chan_lmode;
02586 ci->mlock_redirect = NULL;
02587 }
02588 }
02589
02590
02591
02592
02593
02594 void cs_set_unkwn(ChannelInfo * ci, char *value)
02595 {
02596
02597 }
02598
02599
02600
02601 int get_access_level(ChannelInfo * ci, NickAlias * na)
02602 {
02603 ChanAccess *access;
02604 int num;
02605
02606 if (!ci || !na) {
02607 return 0;
02608 }
02609
02610 if (na->nc == ci->founder) {
02611 return ACCESS_FOUNDER;
02612 }
02613
02614 for (num = 0; num < ci->accesscount; num++) {
02615
02616 access = &ci->access[num];
02617
02618 if (access->nc && access->nc == na->nc && access->in_use) {
02619 return access->level;
02620 }
02621
02622 }
02623
02624 return 0;
02625
02626 }
02627
02628 const char *get_xop_level(int level)
02629 {
02630 if (level < ACCESS_VOP) {
02631 return "Err";
02632 } else if (ircd->halfop && level < ACCESS_HOP) {
02633 return "VOP";
02634 } else if (!ircd->halfop && level < ACCESS_AOP) {
02635 return "VOP";
02636 } else if (ircd->halfop && level < ACCESS_AOP) {
02637 return "HOP";
02638 } else if (level < ACCESS_SOP) {
02639 return "AOP";
02640 } else if (level < ACCESS_FOUNDER) {
02641 return "SOP";
02642 } else {
02643 return "Founder";
02644 }
02645
02646 }
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666 AutoKick *is_stuck(ChannelInfo * ci, char *mask)
02667 {
02668 int i;
02669 AutoKick *akick;
02670
02671 if (!ci) {
02672 return NULL;
02673 }
02674
02675 for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
02676 if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)
02677 || !(akick->flags & AK_STUCK))
02678 continue;
02679
02680 if (match_wild_nocase(mask, akick->u.mask))
02681 return akick;
02682 if (ircd->reversekickcheck) {
02683
02684 if (match_wild_nocase(akick->u.mask, mask))
02685 return akick;
02686 }
02687 }
02688
02689 return NULL;
02690 }
02691
02692
02693
02694 void stick_mask(ChannelInfo * ci, AutoKick * akick)
02695 {
02696 char *av[2];
02697 Entry *ban;
02698
02699 if (!ci) {
02700 return;
02701 }
02702
02703 if (ci->c->bans && ci->c->bans->entries != 0) {
02704 for (ban = ci->c->bans->entries; ban; ban = ban->next) {
02705
02706
02707 if (entry_match_mask(ban, sstrdup(akick->u.mask), 0))
02708 return;
02709
02710 if (ircd->reversekickcheck) {
02711
02712
02713 if (match_wild_nocase(akick->u.mask, ban->mask))
02714 return;
02715 }
02716 }
02717 }
02718
02719
02720 av[0] = sstrdup("+b");
02721 av[1] = akick->u.mask;
02722 anope_cmd_mode(whosends(ci), ci->c->name, "+b %s", akick->u.mask);
02723 chan_set_modes(s_ChanServ, ci->c, 2, av, 1);
02724 free(av[0]);
02725 }
02726
02727
02728
02729 void stick_all(ChannelInfo * ci)
02730 {
02731 int i;
02732 char *av[2];
02733 AutoKick *akick;
02734
02735 if (!ci) {
02736 return;
02737 }
02738
02739 for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
02740 if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)
02741 || !(akick->flags & AK_STUCK))
02742 continue;
02743
02744 av[0] = sstrdup("+b");
02745 av[1] = akick->u.mask;
02746 anope_cmd_mode(whosends(ci), ci->c->name, "+b %s", akick->u.mask);
02747 chan_set_modes(s_ChanServ, ci->c, 2, av, 1);
02748 free(av[0]);
02749 }
02750 }
02751
02755 void CleanAccess(ChannelInfo *ci)
02756 {
02757 int a, b;
02758
02759 if (!ci)
02760 return;
02761
02762 for (b = 0; b < ci->accesscount; b++)
02763 {
02764 if (ci->access[b].in_use)
02765 {
02766 for (a = 0; a < ci->accesscount; a++)
02767 {
02768 if (a > b)
02769 break;
02770 if (!ci->access[a].in_use)
02771 {
02772 ci->access[a].in_use = 1;
02773 ci->access[a].level = ci->access[b].level;
02774 ci->access[a].nc = ci->access[b].nc;
02775 ci->access[a].last_seen = ci->access[b].last_seen;
02776 ci->access[b].nc = NULL;
02777 ci->access[b].in_use = 0;
02778 break;
02779 }
02780 }
02781 }
02782 }
02783
02784
02785 for (b = ci->accesscount - 1; b >= 0; --b)
02786 {
02787 if (ci->access[b].in_use)
02788 break;
02789 ci->accesscount--;
02790 }
02791
02792
02793 ci->access = srealloc(ci->access, sizeof(ChanAccess) * ci->accesscount);
02794 }
02795