/* * Note: * - We write chanmode "" too, so that the bot won't use default-chanmode * instead of "" * - We will write empty need-xxxx too, why not? (less code + lazyness) */ static void write_channels() { FILE *f; char s[121], w[1024], w2[1024], name[163]; char need1[242], need2[242], need3[242], need4[242], need5[242]; struct chanset_t *chan; struct udef_struct *ul; if (!chanfile[0]) return; sprintf(s, "%s~new", chanfile); f = fopen(s, "w"); chmod(s, userfile_perm); if (f == NULL) { putlog(LOG_MISC, "*", "ERROR writing channel file."); return; } if (!quiet_save) putlog(LOG_MISC, "*", "Writing channel file..."); fprintf(f, "#Dynamic Channel File for %s (%s) -- written %s\n", botnetnick, ver, ctime(&now)); for (chan = chanset; chan; chan = chan->next) { convert_element(chan->dname, name); get_mode_protect(chan, w); convert_element(w, w2); convert_element(chan->need_op, need1); convert_element(chan->need_invite, need2); convert_element(chan->need_key, need3); convert_element(chan->need_unban, need4); convert_element(chan->need_limit, need5); fprintf(f, "channel add %s { chanmode %s idle-kick %d stopnethack-mode %d " "revenge-mode %d need-op %s need-invite %s need-key %s " "need-unban %s need-limit %s flood-chan %d:%d flood-ctcp %d:%d " "flood-join %d:%d flood-kick %d:%d flood-deop %d:%d " "flood-nick %d:%d aop-delay %d:%d ban-type %d ban-time %d " "exempt-time %d invite-time %d %cenforcebans %cdynamicbans " "%cuserbans %cautoop %cautohalfop %cbitch %cgreet %cprotectops " "%cprotecthalfops %cprotectfriends %cdontkickops %cstatuslog " "%crevenge %crevengebot %cautovoice %csecret %cshared %ccycle " "%cseen %cinactive %cdynamicexempts %cuserexempts %cdynamicinvites " "%cuserinvites %cnodesynch %cstatic }" "\n", name, w2, chan->idle_kick, chan->stopnethack_mode, chan->revenge_mode, need1, need2, need3, need4, need5, chan->flood_pub_thr, chan->flood_pub_time, chan->flood_ctcp_thr, chan->flood_ctcp_time, chan->flood_join_thr, chan->flood_join_time, chan->flood_kick_thr, chan->flood_kick_time, chan->flood_deop_thr, chan->flood_deop_time, chan->flood_nick_thr, chan->flood_nick_time, chan->aop_min, chan->aop_max, chan->ban_type, chan->ban_time, chan->exempt_time, chan->invite_time, PLSMNS(channel_enforcebans(chan)), PLSMNS(channel_dynamicbans(chan)), PLSMNS(!channel_nouserbans(chan)), PLSMNS(channel_autoop(chan)), PLSMNS(channel_autohalfop(chan)), PLSMNS(channel_bitch(chan)), PLSMNS(channel_greet(chan)), PLSMNS(channel_protectops(chan)), PLSMNS(channel_protecthalfops(chan)), PLSMNS(channel_protectfriends(chan)), PLSMNS(channel_dontkickops(chan)), PLSMNS(channel_logstatus(chan)), PLSMNS(channel_revenge(chan)), PLSMNS(channel_revengebot(chan)), PLSMNS(channel_autovoice(chan)), PLSMNS(channel_secret(chan)), PLSMNS(channel_shared(chan)), PLSMNS(channel_cycle(chan)), PLSMNS(channel_seen(chan)), PLSMNS(channel_inactive(chan)), PLSMNS(channel_dynamicexempts(chan)), PLSMNS(!channel_nouserexempts(chan)), PLSMNS(channel_dynamicinvites(chan)), PLSMNS(!channel_nouserinvites(chan)), PLSMNS(channel_nodesynch(chan)), PLSMNS(channel_static(chan))); for (ul = udef; ul; ul = ul->next) { if (ul->defined && ul->name) { if (ul->type == UDEF_FLAG) fprintf(f, "channel set %s %c%s%s\n", name, getudef(ul->values, chan->dname) ? '+' : '-', "udef-flag-", ul->name); else if (ul->type == UDEF_INT) fprintf(f, "channel set %s %s%s %d\n", name, "udef-int-", ul->name, (int) getudef(ul->values, chan->dname)); else if (ul->type == UDEF_STR) { char *p = (char *) getudef(ul->values, chan->dname); if (!p) p = "{}"; fprintf(f, "channel set %s udef-str-%s %s\n", name, ul->name, p); } else debug1("UDEF-ERROR: unknown type %d", ul->type); } } if (fflush(f)) { putlog(LOG_MISC, "*", "ERROR writing channel file."); fclose(f); return; } } fclose(f); unlink(chanfile); movefile(s, chanfile); }
static void cmd_chaninfo(int idx, char *par) { char *chname = NULL, work[512] = ""; struct chanset_t *chan = NULL; int cnt = 0; if (!par[0]) { chname = dcc[idx].u.chat->con_chan; if (chname[0] == '*') { dprintf(idx, "Your console channel is invalid.\n"); return; } } else { chname = newsplit(&par); get_user_flagrec(dcc[idx].user, &user, chname); if (!glob_master(user) && !chan_master(user)) { dprintf(idx, "You don't have access to %s.\n", chname); return; } } if (!strcasecmp(chname, "default")) chan = chanset_default; else chan = findchan_by_dname(chname); if (!chan || (chan && privchan(user, chan, PRIV_OP))) { dprintf(idx, "No such channel.\n"); return; } else { char nick[HANDLEN + 1] = "", date[81] = ""; int deflag = 0; if (chan->added_ts) { strftime(date, sizeof date, "%c %Z", gmtime(&(chan->added_ts))); } else date[0] = 0; if (chan->added_by && chan->added_by[0]) strlcpy(nick, chan->added_by, sizeof(nick)); else nick[0] = 0; putlog(LOG_CMDS, "*", "#%s# chaninfo %s", dcc[idx].nick, chname); if (nick[0] && date[0]) dprintf(idx, "Settings for channel %s (Added %s by %s%s%s):\n", chan->dname, date, BOLD(idx), nick, BOLD_END(idx)); else dprintf(idx, "Settings for channel %s:\n", chan->dname); /* FIXME: SHOW_CHAR() here */ get_mode_protect(chan, work, sizeof(work)); dprintf(idx, "Protect modes (chanmode): %s\n", work[0] ? work : "None"); dprintf(idx, "Groups: %s\n", chan->groups && chan->groups->length() ? static_cast<bd::String>(chan->groups->join(" ")).c_str() : "None"); dprintf(idx, "FiSH Key: %s\n", chan->fish_key[0] ? chan->fish_key : "not set"); // dprintf(idx, "Protect topic (topic) : %s\n", chan->topic[0] ? chan->topic : ""); /* Chanchar template * dprintf(idx, "String temp: %s\n", chan->temp[0] ? chan->temp : "NULL"); */ dprintf(idx, "Channel flags:\n"); work[0] = 0; SHOW_FLAG("autoop", channel_autoop(chan)); SHOW_FLAG("backup", channel_backup(chan)); SHOW_FLAG("bitch", channel_bitch(chan)); SHOW_FLAG("botbitch", channel_botbitch(chan)); SHOW_FLAG("closed", channel_closed(chan)); SHOW_FLAG("cycle", channel_cycle(chan)); SHOW_FLAG("enforcebans", channel_enforcebans(chan)); SHOW_FLAG("fastop", channel_fastop(chan)); SHOW_FLAG("floodban", channel_floodban(chan)); SHOW_FLAG("inactive", channel_inactive(chan)); SHOW_FLAG("nodesynch", channel_nodesynch(chan)); SHOW_FLAG("private", channel_privchan(chan)); SHOW_FLAG("protect", channel_protect(chan)); SHOW_FLAG("rbl", channel_rbl(chan)); if (HAVE_TAKE) SHOW_FLAG("take", channel_take(chan)); SHOW_FLAG("voice", channel_voice(chan)); SHOW_FLAG("voicebitch", channel_voicebitch(chan)); SHOW_FLAG("", 0); SHOW_FLAG("dynamicbans", channel_dynamicbans(chan)); SHOW_FLAG("userbans", !channel_nouserbans(chan)); SHOW_FLAG("dynamicexempts", channel_dynamicexempts(chan)); SHOW_FLAG("userexempts", !channel_nouserexempts(chan)); SHOW_FLAG("dynamicinvites", channel_dynamicinvites(chan)); SHOW_FLAG("userinvites", !channel_nouserinvites(chan)); SHOW_FLAG("", 0); work[0] = 0; /* Chanflag template * SHOW_FLAG("template", channel_template(chan)); * also include %ctemp in dprintf. */ work[0] = cnt = 0; /* Chanint template * SHOW_INT("Desc: ", integer, "YES", "NO"); */ dprintf(idx, "Channel settings:\n"); deflag = chan->bad_cookie; SHOW_INT("Auto-delay: ", chan->auto_delay, NULL, "None"); SHOW_INT("Bad-cookie:" , chan->bad_cookie, DEFLAG_STR, "Ignore"); SHOW_INT("Ban-time: ", chan->ban_time, NULL, "Forever"); SHOW_INT("Ban-type: ", chan->ban_type, NULL, "3"); SHOW_INT("Closed-ban: ", chan->closed_ban, NULL, "Don't!"); SHOW_INT("Closed-invite:", chan->closed_invite, NULL, "Don't!"); SHOW_INT("Closed-Private:", chan->closed_private, NULL, "Don't!"); SHOW_INT("Closed-Exempt:", chan->closed_exempt_mode, F_STR(chan->closed_exempt_mode), "None"); SHOW_INT("Exempt-time: ", chan->exempt_time, NULL, "Forever"); SHOW_INT("Flood-exempt: ", chan->flood_exempt_mode, F_STR(chan->flood_exempt_mode), "None"); SHOW_INT("Flood-lock-time: ", chan->flood_lock_time, NULL, "Don't"); SHOW_INT("Caps-Limit(%): ", chan->capslimit, NULL, "None"); SHOW_INT("Color-Limit: ", chan->colorlimit, NULL, "None"); SHOW_INT("Invite-time: ", chan->invite_time, NULL, "Forever"); SHOW_INT("Knock: ", chan->knock_flags, F_STR(chan->knock_flags), "None"); SHOW_INT("Limit raise (limit): ", chan->limitraise, NULL, "Disabled"); deflag = chan->manop; SHOW_INT("Manop: ", chan->manop, DEFLAG_STR, "Ignore"); deflag = chan->mdop; SHOW_INT("Mdop: ", chan->mdop, DEFLAG_STR, "Ignore"); deflag = chan->mop; SHOW_INT("Mop: ", chan->mop, DEFLAG_STR, "Ignore"); deflag = chan->revenge; SHOW_INT("Revenge: ", chan->revenge, DEFLAG_STR, "Ignore"); SHOW_INT("Protect-backup: ", chan->protect_backup, "Do!", "Don't!"); SHOW_INT("Voice-non-ident: ", chan->voice_non_ident, "Do!", "Don't!"); SHOW_INT("Voice-moderate:", chan->voice_moderate, "Do!", "Don't!"); dprintf(idx, "Flood settings: chan bytes ctcp join kick deop nick mjoin mpub mbytes mctcp\n"); dprintf(idx, " number: %3d %4d %3d %3d %3d %3d %3d %3d %3d %4d %3d\n", chan->flood_pub_thr, chan->flood_bytes_thr, chan->flood_ctcp_thr, chan->flood_join_thr, chan->flood_kick_thr, chan->flood_deop_thr, chan->flood_nick_thr, chan->flood_mjoin_thr, chan->flood_mpub_thr, chan->flood_mbytes_thr, chan->flood_mctcp_thr); dprintf(idx, " time : %3u %4u %3u %3u %3u %3u %3u %3u %3u %4u %4u\n", chan->flood_pub_time, chan->flood_bytes_time, chan->flood_ctcp_time, chan->flood_join_time, chan->flood_kick_time, chan->flood_deop_time, chan->flood_nick_time, chan->flood_mjoin_time, chan->flood_mpub_time, chan->flood_mbytes_time, chan->flood_mctcp_time); } }
void channels_report(int idx, int details) { int i; char s[1024] = "", s2[100] = ""; struct flag_record fr = {FR_CHAN | FR_GLOBAL, 0, 0, 0 }; for (struct chanset_t *chan = chanset; chan; chan = chan->next) { if (idx != DP_STDOUT) get_user_flagrec(dcc[idx].user, &fr, chan->dname, chan); if (!privchan(fr, chan, PRIV_OP) && ((idx == DP_STDOUT) || glob_master(fr) || chan_master(fr))) { s[0] = 0; if (chan_bitch(chan)) strlcat(s, "bitch, ", sizeof(s)); if (s[0]) s[strlen(s) - 2] = 0; if (!s[0]) strlcpy(s, "lurking", sizeof(s)); get_mode_protect(chan, s2, sizeof(s2)); if (channel_closed(chan)) { if (chan->closed_invite) strlcat(s2, "i", sizeof(s2)); if (chan->closed_private) strlcat(s2, "p", sizeof(s2)); } if (shouldjoin(chan)) { if (channel_active(chan)) { /* If it's a !chan, we want to display it's unique name too <cybah> */ if (chan->dname[0]=='!') { dprintf(idx, " %-20s: %2d member%s enforcing \"%s\" (%s), " "unique name %s\n", chan->dname, chan->channel.members, (chan->channel.members==1) ? "," : "s,", s2, s, chan->name); } else { dprintf(idx, " %-20s: %2d member%s enforcing \"%s\" (%s)\n", chan->dname, chan->channel.members, chan->channel.members == 1 ? "," : "s,", s2, s); } } else { if (!conf.bot->hub) dprintf(idx, " %-20s: (%s), enforcing \"%s\" (%s)\n", chan->dname, channel_pending(chan) ? "pending" : "not on channel", s2, s); else dprintf(idx, " %-20s: (%s), enforcing \"%s\" (%s)\n", chan->dname, "limbo", s2, s); } } else { dprintf(idx, " %-20s: channel is set +inactive\n", chan->dname); } if (details) { s[0] = 0; i = 0; i += my_strcpy(s + i, "dynamic "); if (channel_enforcebans(chan)) i += my_strcpy(s + i, "enforcebans "); if (channel_dynamicbans(chan)) i += my_strcpy(s + i, "dynamicbans "); if (!channel_nouserbans(chan)) i += my_strcpy(s + i, "userbans "); if (channel_bitch(chan)) i += my_strcpy(s + i, "bitch "); /* if (channel_revenge(chan)) i += my_strcpy(s + i, "revenge "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revengebot "); */ if (channel_secret(chan)) i += my_strcpy(s + i, "secret "); if (channel_cycle(chan)) i += my_strcpy(s + i, "cycle "); if (channel_dynamicexempts(chan)) i += my_strcpy(s + i, "dynamicexempts "); if (!channel_nouserexempts(chan)) i += my_strcpy(s + i, "userexempts "); if (channel_dynamicinvites(chan)) i += my_strcpy(s + i, "dynamicinvites "); if (!channel_nouserinvites(chan)) i += my_strcpy(s + i, "userinvites "); if (!shouldjoin(chan)) i += my_strcpy(s + i, "inactive "); if (channel_nodesynch(chan)) i += my_strcpy(s + i, "nodesynch "); if (channel_closed(chan)) i += my_strcpy(s + i, "closed "); if (HAVE_TAKE && channel_take(chan)) i += my_strcpy(s + i, "take "); if (channel_voice(chan)) i += my_strcpy(s + i, "voice "); if (channel_autoop(chan)) i += my_strcpy(s + i, "autoop "); if (channel_meankicks(chan)) i += my_strcpy(s + i, "meankicks "); if (channel_rbl(chan)) i += my_strcpy(s + i, "rbl "); if (channel_voicebitch(chan)) i += my_strcpy(s + i, "voicebitch "); if (channel_protect(chan)) i += my_strcpy(s + i, "protect "); /* Chanflag template * if (channel_temp(chan)) * i += my_strcpy(s + i, "temp "); */ if (channel_nomassjoin(chan)) i += my_strcpy(s + i, "nomassjoin "); if (channel_botbitch(chan)) i += my_strcpy(s + i, "botbitch "); if (channel_backup(chan)) i += my_strcpy(s + i, "backup "); if (channel_fastop(chan)) i += my_strcpy(s + i, "fastop "); if (channel_privchan(chan)) i += my_strcpy(s + i, "private "); dprintf(idx, " Options: %s\n", s); if (chan->limitraise) dprintf(idx, " Raising limit +%d every 2 minutes\n", chan->limitraise); /* if (chan->revenge_mode) dprintf(idx, " revenge-mode %d\n", chan->revenge_mode); */ dprintf(idx, " Bans last %d mins.\n", chan->ban_time); dprintf(idx, " Exemptions last %d mins.\n", chan->exempt_time); dprintf(idx, " Invitations last %d mins.\n", chan->invite_time); } } } }
static void got_deop(struct chanset_t *chan, char *nick, char *from, char *who, struct userrec *opu) { memberlist *m; char ch[sizeof chan->name]; char s[UHOSTLEN], s1[UHOSTLEN]; struct userrec *u; int had_halfop; m = ismember(chan, who); if (!m) { if (channel_pending(chan)) return; putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who); chan->status |= CHAN_PEND; refresh_who_chan(chan->name); return; } strcpy(ch, chan->name); simple_sprintf(s, "%s!%s", m->nick, m->userhost); simple_sprintf(s1, "%s!%s", nick, from); u = get_user_by_host(s); get_user_flagrec(u, &victim, chan->dname); had_halfop = chan_hasop(m); /* Flags need to be set correctly right from the beginning now, so that * add_mode() doesn't get irritated. */ m->flags &= ~(CHANOP | SENTDEOP | FAKEOP); check_tcl_mode(nick, from, opu, chan->dname, "-o", who); if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) || !(m = ismember(chan, who))) return; m->flags &= ~WASOP; if (channel_pending(chan)) return; if (HALFOP_CANDOMODE('o')) { int ok = 1; if (!glob_deop(victim) && !chan_deop(victim)) { if (channel_protectops(chan) && (glob_master(victim) || chan_master(victim) || glob_op(victim) || chan_op(victim))) ok = 0; else if (channel_protectfriends(chan) && (glob_friend(victim) || chan_friend(victim))) ok = 0; } if ((reversing || !ok) && had_halfop && !match_my_nick(nick) && rfc_casecmp(who, nick) && !match_my_nick(who) && !glob_master(user) && !chan_master(user) && !glob_bot(user) && ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) || !channel_bitch(chan))) add_mode(chan, '+', 'o', who); } if (!nick[0]) putlog(LOG_MODES, chan->dname, "TS resync (%s): %s deopped by %s", chan->dname, who, from); /* Check for mass deop */ if (nick[0]) detect_chan_flood(nick, from, s1, chan, FLOOD_DEOP, who, 0); /* Having op hides your +v and +h status -- so now that someone's lost ops, * check to see if they have +v or +h */ if (!(m->flags & (CHANVOICE | CHANHALFOP | STOPWHO))) { chan->status |= CHAN_PEND; refresh_who_chan(chan->name); m->flags |= STOPWHO; } /* Was the bot deopped? */ if (match_my_nick(who)) { /* Cancel any pending kicks and modes */ memberlist *m2; for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next) m2->flags &= ~(SENTKICK | SENTDEOP | SENTOP | SENTVOICE | SENTDEVOICE); check_tcl_need(chan->dname, "op"); if (chan->need_op[0]) do_tcl("need-op", chan->need_op); if (!nick[0]) putlog(LOG_MODES, chan->dname, "TS resync deopped me on %s :(", chan->dname); } if (nick[0]) maybe_revenge(chan, s1, s, REVENGE_DEOP); }
static void got_dehalfop(struct chanset_t *chan, char *nick, char *from, char *who, struct userrec *opu) { memberlist *m; char ch[sizeof chan->name]; char s[UHOSTLEN], s1[UHOSTLEN]; struct userrec *u; int had_halfop; m = ismember(chan, who); if (!m) { if (channel_pending(chan)) return; putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who); chan->status |= CHAN_PEND; refresh_who_chan(chan->name); return; } strcpy(ch, chan->name); simple_sprintf(s, "%s!%s", m->nick, m->userhost); simple_sprintf(s1, "%s!%s", nick, from); u = get_user_by_host(s); get_user_flagrec(u, &victim, chan->dname); had_halfop = chan_hasop(m); /* Flags need to be set correctly right from the beginning now, so that * add_mode() doesn't get irritated. */ m->flags &= ~(CHANHALFOP | SENTDEHALFOP | FAKEHALFOP); check_tcl_mode(nick, from, opu, chan->dname, "-h", who); if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) || !(m = ismember(chan, who))) return; /* Check comments in got_op() (drummer) */ m->flags &= ~WASHALFOP; if (channel_pending(chan)) return; /* Dehalfop'd someone on my oplist? */ if (HALFOP_CANDOMODE('h')) { int ok = 1; if (!glob_dehalfop(victim) && !chan_dehalfop(victim)) { if (channel_protecthalfops(chan) && (glob_master(victim) || chan_master(victim) || glob_halfop(victim) || chan_halfop(victim))) ok = 0; else if (channel_protectfriends(chan) && (glob_friend(victim) || chan_friend(victim))) ok = 0; } if ((reversing || !ok) && had_halfop && !match_my_nick(nick) && rfc_casecmp(who, nick) && !match_my_nick(who) && !glob_master(user) && !chan_master(user) && !glob_bot(user) && ((chan_halfop(victim) || (glob_halfop(victim) && !chan_dehalfop(victim))) || !channel_bitch(chan))) add_mode(chan, '+', 'h', who); } if (!nick[0]) putlog(LOG_MODES, chan->dname, "TS resync (%s): %s deopped by %s", chan->dname, who, from); if (!(m->flags & (CHANVOICE | STOPWHO))) { chan->status |= CHAN_PEND; refresh_who_chan(chan->name); m->flags |= STOPWHO; } }
static void got_halfop(struct chanset_t *chan, char *nick, char *from, char *who, struct userrec *opu, struct flag_record *opper) { memberlist *m; char s[UHOSTLEN]; char ch[sizeof chan->name]; struct userrec *u; int check_chan = 0; int snm = chan->stopnethack_mode; m = ismember(chan, who); if (!m) { if (channel_pending(chan)) return; putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who); chan->status |= CHAN_PEND; refresh_who_chan(chan->name); return; } /* Did *I* just get halfopped? */ if (!me_op(chan) && !me_halfop(chan) && match_my_nick(who)) check_chan = 1; strcpy(ch, chan->name); simple_sprintf(s, "%s!%s", m->nick, m->userhost); if (!m->user) u = get_user_by_host(s); else u = m->user; get_user_flagrec(u, &victim, chan->dname); /* Flags need to be set correctly right from the beginning now, so that * add_mode() doesn't get irritated. */ m->flags |= CHANHALFOP; check_tcl_mode(nick, from, opu, chan->dname, "+h", who); if (!(chan = modebind_refresh(ch, from, opper, s, &victim)) || !(m = ismember(chan, who))) return; m->flags &= ~SENTHALFOP; if (channel_pending(chan)) return; if (nick[0] && HALFOP_CANDOMODE('h') && !match_my_nick(who) && !match_my_nick(nick)) { if (channel_bitch(chan) && !(glob_master(*opper) || glob_bot(*opper)) && !chan_master(*opper) && !(glob_halfop(victim) || glob_op(victim) || glob_bot(victim)) && !chan_op(victim) && !chan_halfop(victim)) add_mode(chan, '-', 'h', who); else if ((chan_dehalfop(victim) || (glob_dehalfop(victim) && !chan_halfop(victim))) && !glob_master(*opper) && !chan_master(*opper)) add_mode(chan, '-', 'h', who); else if (reversing) add_mode(chan, '-', 'h', who); } else if (reversing && HALFOP_CANDOMODE('h') && !match_my_nick(who) && !match_my_nick(nick)) add_mode(chan, '-', 'h', who); if (!nick[0] && HALFOP_CANDOMODE('h') && !match_my_nick(who)) { if (chan_dehalfop(victim) || (glob_dehalfop(victim) && !chan_halfop(victim))) { m->flags |= FAKEHALFOP; add_mode(chan, '-', 'h', who); } else if (snm > 0 && snm < 7 && !((channel_autohalfop(chan) || glob_autohalfop(victim) || chan_autohalfop(victim)) && (chan_halfop(victim) || (glob_halfop(victim) && !chan_dehalfop(victim)))) && !glob_exempt(victim) && !chan_exempt(victim)) { if (snm == 5) snm = channel_bitch(chan) ? 1 : 3; if (snm == 6) snm = channel_bitch(chan) ? 4 : 2; if (chan_washalfoptest(victim) || glob_washalfoptest(victim) || snm == 2) { if (!chan_washalfop(m)) { m->flags |= FAKEHALFOP; add_mode(chan, '-', 'h', who); } } else if (!(chan_halfop(victim) || (glob_halfop(victim) && !chan_dehalfop(victim)))) { if (snm == 1 || snm == 4 || (snm == 3 && !chan_washalfop(m))) { add_mode(chan, '-', 'h', who); m->flags |= FAKEHALFOP; } } else if (snm == 4 && !chan_washalfop(m)) { add_mode(chan, '-', 'h', who); m->flags |= FAKEHALFOP; } } } m->flags |= WASHALFOP; if (check_chan) recheck_channel(chan, 1); }
static void channels_report(int idx, int details) { struct chanset_t *chan; int i; char s[1024], s2[100]; struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0, 0, 0 }; for (chan = chanset; chan; chan = chan->next) { if (idx != DP_STDOUT) get_user_flagrec(dcc[idx].user, &fr, chan->dname); if ((idx == DP_STDOUT) || glob_master(fr) || chan_master(fr)) { s[0] = 0; if (channel_greet(chan)) strcat(s, "greet, "); if (channel_autoop(chan)) strcat(s, "auto-op, "); if (channel_bitch(chan)) strcat(s, "bitch, "); if (s[0]) s[strlen(s) - 2] = 0; if (!s[0]) strcpy(s, MISC_LURKING); get_mode_protect(chan, s2); if (!channel_inactive(chan)) { if (channel_active(chan)) { /* If it's a !chan, we want to display it's unique name too <cybah> */ if (chan->dname[0] == '!') { dprintf(idx, " %-20s: %3d member%s enforcing \"%s\" (%s), " "unique name %s\n", chan->dname, chan->channel.members, (chan->channel.members == 1) ? "," : "s,", s2, s, chan->name); } else { dprintf(idx, " %-20s: %3d member%s enforcing \"%s\" (%s)\n", chan->dname, chan->channel.members, chan->channel.members == 1 ? "," : "s,", s2, s); } } else { dprintf(idx, " %-20s: (%s), enforcing \"%s\" (%s)\n", chan->dname, channel_pending(chan) ? "pending" : "not on channel", s2, s); } } else { dprintf(idx, " %-20s: channel is set +inactive\n", chan->dname); } if (details) { s[0] = 0; i = 0; if (channel_enforcebans(chan)) i += my_strcpy(s + i, "enforcebans "); if (channel_dynamicbans(chan)) i += my_strcpy(s + i, "dynamicbans "); if (!channel_nouserbans(chan)) i += my_strcpy(s + i, "userbans "); if (channel_autoop(chan)) i += my_strcpy(s + i, "autoop "); if (channel_bitch(chan)) i += my_strcpy(s + i, "bitch "); if (channel_greet(chan)) i += my_strcpy(s + i, "greet "); if (channel_protectops(chan)) i += my_strcpy(s + i, "protectops "); if (channel_protecthalfops(chan)) i += my_strcpy(s + i, "protecthalfops "); if (channel_protectfriends(chan)) i += my_strcpy(s + i, "protectfriends "); if (channel_dontkickops(chan)) i += my_strcpy(s + i, "dontkickops "); if (channel_logstatus(chan)) i += my_strcpy(s + i, "statuslog "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revenge "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revengebot "); if (channel_secret(chan)) i += my_strcpy(s + i, "secret "); if (channel_shared(chan)) i += my_strcpy(s + i, "shared "); if (!channel_static(chan)) i += my_strcpy(s + i, "dynamic "); if (channel_autovoice(chan)) i += my_strcpy(s + i, "autovoice "); if (channel_autohalfop(chan)) i += my_strcpy(s + i, "autohalfop "); if (channel_cycle(chan)) i += my_strcpy(s + i, "cycle "); if (channel_dynamicexempts(chan)) i += my_strcpy(s + i, "dynamicexempts "); if (!channel_nouserexempts(chan)) i += my_strcpy(s + i, "userexempts "); if (channel_dynamicinvites(chan)) i += my_strcpy(s + i, "dynamicinvites "); if (!channel_nouserinvites(chan)) i += my_strcpy(s + i, "userinvites "); if (channel_inactive(chan)) i += my_strcpy(s + i, "inactive "); if (channel_nodesynch(chan)) i += my_strcpy(s + i, "nodesynch "); dprintf(idx, " Options: %s\n", s); if (chan->need_op[0]) dprintf(idx, " To get ops, I do: %s\n", chan->need_op); if (chan->need_invite[0]) dprintf(idx, " To get invited, I do: %s\n", chan->need_invite); if (chan->need_limit[0]) dprintf(idx, " To get the channel limit raised, I do: %s\n", chan->need_limit); if (chan->need_unban[0]) dprintf(idx, " To get unbanned, I do: %s\n", chan->need_unban); if (chan->need_key[0]) dprintf(idx, " To get the channel key, I do: %s\n", chan->need_key); if (chan->stopnethack_mode) dprintf(idx, " stopnethack-mode: %d\n", chan->stopnethack_mode); if (chan->revenge_mode) dprintf(idx, " revenge-mode: %d\n", chan->revenge_mode); dprintf(idx, " Bans last %d minute%s.\n", chan->ban_time, (chan->ban_time != 1) ? "s" : ""); dprintf(idx, " Exemptions last %d minute%s.\n", chan->exempt_time, (chan->exempt_time != 1) ? "s" : ""); dprintf(idx, " Invitations last %d minute%s.\n", chan->invite_time, (chan->invite_time != 1) ? "s" : ""); } } } }
static void channels_report(int idx, int details) { struct chanset_t *chan; int i; char s[1024], s2[100]; struct flag_record fr = {FR_CHAN | FR_GLOBAL, 0, 0, 0, 0, 0}; chan = chanset; while (chan != NULL) { if (idx != DP_STDOUT) get_user_flagrec(dcc[idx].user, &fr, chan->name); if ((idx == DP_STDOUT) || glob_master(fr) || chan_master(fr)) { s[0] = 0; if (channel_greet(chan)) strcat(s, "greet, "); if (channel_autoop(chan)) strcat(s, "auto-op, "); if (channel_bitch(chan)) strcat(s, "bitch, "); if (s[0]) s[strlen(s) - 2] = 0; if (!s[0]) strcpy(s, MISC_LURKING); get_mode_protect(chan, s2); if (!channel_inactive(chan)) { if (channel_active(chan)) { dprintf(idx, " %-10s: %2d member%s enforcing \"%s\" (%s)\n", chan->name, chan->channel.members, chan->channel.members == 1 ? "," : "s,", s2, s); } else { dprintf(idx, " %-10s: (%s), enforcing \"%s\" (%s)\n", chan->name, channel_pending(chan) ? "pending" : "inactive", s2, s); } } else { dprintf(idx, " %-10s: no IRC support for this channel\n", chan->name); } if (details) { s[0] = 0; i = 0; if (channel_clearbans(chan)) i += my_strcpy(s + i, "clear-bans "); if (channel_enforcebans(chan)) i += my_strcpy(s + i, "enforce-bans "); if (channel_dynamicbans(chan)) i += my_strcpy(s + i, "dynamic-bans "); if (channel_nouserbans(chan)) i += my_strcpy(s + i, "forbid-user-bans "); if (channel_autoop(chan)) i += my_strcpy(s + i, "op-on-join "); if (channel_bitch(chan)) i += my_strcpy(s + i, "bitch "); if (channel_greet(chan)) i += my_strcpy(s + i, "greet "); if (channel_protectops(chan)) i += my_strcpy(s + i, "protect-ops "); if (channel_protectfriends(chan)) i += my_strcpy(s + i, "protect-friends "); if (channel_dontkickops(chan)) i += my_strcpy(s + i, "dont-kick-ops "); if (channel_wasoptest(chan)) i += my_strcpy(s + i, "was-op-test "); if (channel_logstatus(chan)) i += my_strcpy(s + i, "log-status "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revenge "); if (channel_stopnethack(chan)) i += my_strcpy(s + i, "stopnethack "); if (channel_secret(chan)) i += my_strcpy(s + i, "secret "); if (channel_shared(chan)) i += my_strcpy(s + i, "shared "); if (!channel_static(chan)) i += my_strcpy(s + i, "dynamic "); if (channel_autovoice(chan)) i += my_strcpy(s + i, "autovoice "); if (channel_cycle(chan)) i += my_strcpy(s + i, "cycle "); if (channel_seen(chan)) i += my_strcpy(s + i, "seen "); if (channel_dynamicexempts(chan)) i += my_strcpy(s + i, "dynamic-exempts "); if (channel_nouserexempts(chan)) i += my_strcpy(s + i, "forbid-user-exempts "); if (channel_dynamicinvites(chan)) i += my_strcpy(s + i, "dynamic-invites "); if (channel_nouserinvites(chan)) i += my_strcpy(s + i, "forbid-user-invites "); if (channel_inactive(chan)) i += my_strcpy(s + i, "inactive "); dprintf(idx, " Options: %s\n", s); if (chan->need_op[0]) dprintf(idx, " To get ops I do: %s\n", chan->need_op); if (chan->need_invite[0]) dprintf(idx, " To get invited I do: %s\n", chan->need_invite); if (chan->need_limit[0]) dprintf(idx, " To get the channel limit up'd I do: %s\n", chan->need_limit); if (chan->need_unban[0]) dprintf(idx, " To get unbanned I do: %s\n", chan->need_unban); if (chan->need_key[0]) dprintf(idx, " To get the channel key I do: %s\n", chan->need_key); if (chan->idle_kick) dprintf(idx, " Kicking idle users after %d min\n", chan->idle_kick); } } chan = chan->next; } if (details) { dprintf(idx, " Bans last %d mins.\n", ban_time); dprintf(idx, " Exemptions last %d mins.\n", exempt_time); dprintf(idx, " Invitations last %d mins.\n", invite_time); } }
static void write_channels() { FILE *f; char s[121], w[1024], w2[1024], name[163]; char need1[242], need2[242], need3[242], need4[242], need5[242]; struct chanset_t *chan; Context; if (!chanfile[0]) return; sprintf(s, "%s~new", chanfile); f = fopen(s, "w"); chmod(s, 0600); if (f == NULL) { putlog(LOG_MISC, "*", "ERROR writing channel file."); return; } if (!quiet_save) putlog(LOG_MISC, "*", "Writing channel file ..."); fprintf(f, "#Dynamic Channel File for %s (%s) -- written %s\n", origbotname, ver, ctime(&now)); for (chan = chanset; chan; chan = chan->next) { convert_element(chan->name, name); get_mode_protect(chan, w); convert_element(w, w2); convert_element(chan->need_op, need1); convert_element(chan->need_invite, need2); convert_element(chan->need_key, need3); convert_element(chan->need_unban, need4); convert_element(chan->need_limit, need5); fprintf(f, "channel %s %s%schanmode %s idle-kick %d \ need-op %s need-invite %s need-key %s need-unban %s need-limit %s \ flood-chan %d:%d flood-ctcp %d:%d flood-join %d:%d \ flood-kick %d:%d flood-deop %d:%d \ %cclearbans %cenforcebans %cdynamicbans %cuserbans %cautoop %cbitch \ %cgreet %cprotectops %cprotectfriends %cdontkickops %cwasoptest \ %cstatuslog %cstopnethack %crevenge %crevengebot %cautovoice %csecret \ %cshared %ccycle %cseen %cinactive %cdynamicexempts %cuserexempts \ %cdynamicinvites %cuserinvites%s\n", channel_static(chan) ? "set" : "add", name, channel_static(chan) ? " " : " { ", w2, /* now bot write chanmode "" too, * so bot wont use default-chanmode instead of "" -- bugfix */ chan->idle_kick, /* idle-kick 0 is same as dont-idle-kick (less code)*/ need1, need2, need3, need4, need5, /* yes we will write empty need-xxxx too, why not? (less code + lazyness) */ chan->flood_pub_thr, chan->flood_pub_time, chan->flood_ctcp_thr, chan->flood_ctcp_time, chan->flood_join_thr, chan->flood_join_time, chan->flood_kick_thr, chan->flood_kick_time, chan->flood_deop_thr, chan->flood_deop_time, PLSMNS(channel_clearbans(chan)), PLSMNS(channel_enforcebans(chan)), PLSMNS(channel_dynamicbans(chan)), PLSMNS(!channel_nouserbans(chan)), PLSMNS(channel_autoop(chan)), PLSMNS(channel_bitch(chan)), PLSMNS(channel_greet(chan)), PLSMNS(channel_protectops(chan)), PLSMNS(channel_protectfriends(chan)), PLSMNS(channel_dontkickops(chan)), PLSMNS(channel_wasoptest(chan)), PLSMNS(channel_logstatus(chan)), PLSMNS(channel_stopnethack(chan)), PLSMNS(channel_revenge(chan)), PLSMNS(channel_revengebot(chan)), PLSMNS(channel_autovoice(chan)), PLSMNS(channel_secret(chan)), PLSMNS(channel_shared(chan)), PLSMNS(channel_cycle(chan)), PLSMNS(channel_seen(chan)), PLSMNS(channel_inactive(chan)), PLSMNS(channel_dynamicexempts(chan)), PLSMNS(!channel_nouserexempts(chan)), PLSMNS(channel_dynamicinvites(chan)), PLSMNS(!channel_nouserinvites(chan)), channel_static(chan) ? "" : " }"); if (fflush(f)) { putlog(LOG_MISC, "*", "ERROR writing channel file."); fclose(f); return; } } fclose(f); unlink(chanfile); movefile(s, chanfile); }
/* * Note: * - We write chanmode "" too, so that the bot won't use default-chanmode * instead of "" * - We will write empty need-xxxx too, why not? (less code + lazyness) */ static void write_channels() { FILE *f; char s[121], w[1024], w2[1024], name[163]; char need1[242], need2[242], need3[242], need4[242], need5[242]; struct chanset_t *chan; struct udef_struct *ul; Context; if (!chanfile[0]) return; sprintf(s, "%s~new", chanfile); f = fopen(s, "w"); chmod(s, userfile_perm); if (f == NULL) { putlog(LOG_MISC, "*", "ERROR writing channel file."); return; } if (!quiet_save) putlog(LOG_MISC, "*", "Writing channel file ..."); fprintf(f, "#Dynamic Channel File for %s (%s) -- written %s\n", origbotname, ver, ctime(&now)); for (chan = chanset; chan; chan = chan->next) { convert_element(chan->dname, name); get_mode_protect(chan, w); convert_element(w, w2); convert_element(chan->need_op, need1); convert_element(chan->need_invite, need2); convert_element(chan->need_key, need3); convert_element(chan->need_unban, need4); convert_element(chan->need_limit, need5); fprintf(f, "channel %s %s%schanmode %s idle-kick %d stopnethack-mode %d \ need-op %s need-invite %s need-key %s need-unban %s need-limit %s \ flood-chan %d:%d flood-ctcp %d:%d flood-join %d:%d \ flood-kick %d:%d flood-deop %d:%d flood-nick %d:%d \ %cclearbans %cenforcebans %cdynamicbans %cuserbans %cautoop %cbitch \ %cgreet %cprotectops %cprotectfriends %cdontkickops \ %cstatuslog %crevenge %crevengebot %cautovoice %csecret \ %cshared %ccycle %cseen %cinactive %cdynamicexempts %cuserexempts \ %cdynamicinvites %cuserinvites %cnodesynch ", channel_static(chan) ? "set" : "add", name, channel_static(chan) ? " " : " { ", w2, chan->idle_kick, /* idle-kick 0 is same as dont-idle-kick (less code)*/ chan->stopnethack_mode, need1, need2, need3, need4, need5, chan->flood_pub_thr, chan->flood_pub_time, chan->flood_ctcp_thr, chan->flood_ctcp_time, chan->flood_join_thr, chan->flood_join_time, chan->flood_kick_thr, chan->flood_kick_time, chan->flood_deop_thr, chan->flood_deop_time, chan->flood_nick_thr, chan->flood_nick_time, PLSMNS(channel_clearbans(chan)), PLSMNS(channel_enforcebans(chan)), PLSMNS(channel_dynamicbans(chan)), PLSMNS(!channel_nouserbans(chan)), PLSMNS(channel_autoop(chan)), PLSMNS(channel_bitch(chan)), PLSMNS(channel_greet(chan)), PLSMNS(channel_protectops(chan)), PLSMNS(channel_protectfriends(chan)), PLSMNS(channel_dontkickops(chan)), PLSMNS(channel_logstatus(chan)), PLSMNS(channel_revenge(chan)), PLSMNS(channel_revengebot(chan)), PLSMNS(channel_autovoice(chan)), PLSMNS(channel_secret(chan)), PLSMNS(channel_shared(chan)), PLSMNS(channel_cycle(chan)), PLSMNS(channel_seen(chan)), PLSMNS(channel_inactive(chan)), PLSMNS(channel_dynamicexempts(chan)), PLSMNS(!channel_nouserexempts(chan)), PLSMNS(channel_dynamicinvites(chan)), PLSMNS(!channel_nouserinvites(chan)), PLSMNS(channel_nodesynch(chan))); for (ul = udef; ul; ul = ul->next) { if (ul->defined && ul->name) { if (ul->type == UDEF_FLAG) fprintf(f, "%c%s%s ", getudef(ul->values, chan->dname) ? '+' : '-', "udef-flag-", ul->name); else if (ul->type == UDEF_INT) fprintf(f, "%s%s %d ", "udef-int-", ul->name, getudef(ul->values, chan->dname)); else debug1("UDEF-ERROR: unknown type %d", ul->type); } } fprintf(f, "%s\n", channel_static(chan) ? "" : "}"); if (fflush(f)) { putlog(LOG_MISC, "*", "ERROR writing channel file."); fclose(f); return; } } fclose(f); unlink(chanfile); movefile(s, chanfile); }