void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; const Anope::string &chdesc = params.size() > 1 ? params[1] : ""; User *u = source.u; Channel *c = findchan(params[0]); ChannelInfo *ci = cs_findchan(params[0]); if (readonly) source.Reply(_("Sorry, channel registration is temporarily disabled.")); else if (u->Account()->HasFlag(NI_UNCONFIRMED)) source.Reply(_("You must confirm your account before you can register a channel.")); else if (chan[0] == '&') source.Reply(_("Local channels cannot be registered.")); else if (chan[0] != '#') source.Reply(CHAN_SYMBOL_REQUIRED); else if (!ircdproto->IsChannelValid(chan)) source.Reply(CHAN_X_INVALID, chan.c_str()); else if (ci) source.Reply(_("Channel \002%s\002 is already registered!"), chan.c_str()); else if (c && !c->HasUserStatus(u, CMODE_OP)) source.Reply(_("You must be a channel operator to register the channel.")); else if (Config->CSMaxReg && u->Account()->channelcount >= Config->CSMaxReg && !u->HasPriv("chanserv/no-register-limit")) source.Reply(u->Account()->channelcount > Config->CSMaxReg ? CHAN_EXCEEDED_CHANNEL_LIMIT : _(CHAN_REACHED_CHANNEL_LIMIT), Config->CSMaxReg); else { ci = new ChannelInfo(chan); ci->SetFounder(u->Account()); if (!chdesc.empty()) ci->desc = chdesc; ci->mode_locks = def_mode_locks; for (ChannelInfo::ModeList::iterator it = ci->mode_locks.begin(), it_end = ci->mode_locks.end(); it != it_end; ++it) { it->second.setter = u->nick; it->second.ci = ci; } if (c && !c->topic.empty()) { ci->last_topic = c->topic; ci->last_topic_setter = c->topic_setter; ci->last_topic_time = c->topic_time; } else ci->last_topic_setter = source.owner->nick; Log(LOG_COMMAND, u, this, ci); source.Reply(_("Channel \002%s\002 registered under your nickname: %s"), chan.c_str(), u->nick.c_str()); /* Implement new mode lock */ if (c) { check_modes(c); ChannelMode *cm; if (u->FindChannel(c) != NULL) { /* On most ircds you do not receive the admin/owner mode till its registered */ if ((cm = ModeManager::FindChannelModeByName(CMODE_OWNER))) c->SetMode(NULL, cm, u->nick); else if ((cm = ModeManager::FindChannelModeByName(CMODE_PROTECT))) c->RemoveMode(NULL, cm, u->nick); } /* Mark the channel as persistent */ if (c->HasMode(CMODE_PERM)) ci->SetFlag(CI_PERSIST); /* Persist may be in def cflags, set it here */ else if (ci->HasFlag(CI_PERSIST) && (cm = ModeManager::FindChannelModeByName(CMODE_PERM))) c->SetMode(NULL, CMODE_PERM); } FOREACH_MOD(I_OnChanRegistered, OnChanRegistered(ci)); } return; }
void OnDelCore(NickCore *nc) { // XXX this is slightly inefficient for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end;) { ChannelInfo *ci = it->second; ++it; if (ci->GetFounder() == nc) { NickCore *newowner = NULL; if (ci->successor && (ci->successor->IsServicesOper() || !Config->CSMaxReg || ci->successor->channelcount < Config->CSMaxReg)) newowner = ci->successor; else { ChanAccess *highest = NULL; for (unsigned j = 0; j < ci->GetAccessCount(); ++j) { ChanAccess *ca = ci->GetAccess(j); NickCore *anc = findcore(ca->mask); if (!anc || (!anc->IsServicesOper() && Config->CSMaxReg && anc->channelcount >= Config->CSMaxReg) || (anc == nc)) continue; if (!highest || *ca > *highest) highest = ca; } if (highest) newowner = findcore(highest->mask); } if (newowner) { Log(LOG_NORMAL, "chanserv/expire") << "Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to " << newowner->display; ci->SetFounder(newowner); ci->successor = NULL; } else { Log(LOG_NORMAL, "chanserv/expire") << "Deleting channel " << ci->name << " owned by deleted nick " << nc->display; delete ci; continue; } } if (ci->successor == nc) ci->successor = NULL; for (unsigned j = 0; j < ci->GetAccessCount(); ++j) { ChanAccess *ca = ci->GetAccess(j); NickCore *anc = findcore(ca->mask); if (anc && anc == nc) { ci->EraseAccess(j); break; } } for (unsigned j = ci->GetAkickCount(); j > 0; --j) { AutoKick *akick = ci->GetAkick(j - 1); if (akick->HasFlag(AK_ISNICK) && akick->nc == nc) ci->EraseAkick(j - 1); } } }