bool ChanAccess::Matches(const User *u, const NickCore *acc, Path &p) const { if (this->nc) return this->nc == acc; if (u) { bool is_mask = this->mask.find_first_of("!@?*") != Anope::string::npos; if (is_mask && Anope::Match(u->nick, this->mask)) return true; else if (Anope::Match(u->GetDisplayedMask(), this->mask)) return true; } if (acc) { for (unsigned i = 0; i < acc->aliases->size(); ++i) { const NickAlias *na = acc->aliases->at(i); if (Anope::Match(na->nick, this->mask)) return true; } } if (IRCD->IsChannelValid(this->mask)) { ChannelInfo *tci = ChannelInfo::Find(this->mask); if (tci) { for (unsigned i = 0; i < tci->GetAccessCount(); ++i) { ChanAccess *a = tci->GetAccess(i); std::pair<const ChanAccess *, const ChanAccess *> pair = std::make_pair(this, a); std::pair<Set::iterator, Set::iterator> range = p.first.equal_range(this); for (; range.first != range.second; ++range.first) if (range.first->first == pair.first && range.first->second == pair.second) goto cont; p.first.insert(pair); if (a->Matches(u, acc, p)) p.second.insert(pair); cont:; } return p.second.count(this) > 0; } } return false; }
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &channel = params[0]; const Anope::string &target = params[1]; Anope::string what = params.size() > 2 ? params[2] : ""; User *u = source.u; ChannelInfo *ci = cs_findchan(params[0]); if (ci == NULL) { source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); return; } if (!ci->AccessFor(u).HasPriv("SET")) { source.Reply(ACCESS_DENIED); return; } ChannelInfo *target_ci = cs_findchan(target); if (!target_ci) { source.Reply(CHAN_X_NOT_REGISTERED, target.c_str()); return; } if (!IsFounder(u, ci) || !IsFounder(u, target_ci)) { source.Reply(ACCESS_DENIED); return; } if (what.equals_ci("ALL")) what.clear(); if (what.empty()) { delete target_ci; target_ci = new ChannelInfo(*ci); target_ci->name = target; RegisteredChannelList[target_ci->name] = target_ci; target_ci->c = findchan(target_ci->name); if (target_ci->c) { target_ci->c->ci = target_ci; check_modes(target_ci->c); ChannelMode *cm; if (u->FindChannel(target_ci->c) != NULL) { /* On most ircds you do not receive the admin/owner mode till its registered */ if ((cm = ModeManager::FindChannelModeByName(CMODE_OWNER))) target_ci->c->SetMode(NULL, cm, u->nick); else if ((cm = ModeManager::FindChannelModeByName(CMODE_PROTECT))) target_ci->c->RemoveMode(NULL, cm, u->nick); } /* Mark the channel as persistent */ if (target_ci->c->HasMode(CMODE_PERM)) target_ci->SetFlag(CI_PERSIST); /* Persist may be in def cflags, set it here */ else if (target_ci->HasFlag(CI_PERSIST) && (cm = ModeManager::FindChannelModeByName(CMODE_PERM))) target_ci->c->SetMode(NULL, CMODE_PERM); if (target_ci->bi && target_ci->c->FindUser(target_ci->bi) == NULL) target_ci->bi->Join(target_ci->c, &Config->BotModeList); } if (target_ci->c && !target_ci->c->topic.empty()) { target_ci->last_topic = target_ci->c->topic; target_ci->last_topic_setter = target_ci->c->topic_setter; target_ci->last_topic_time = target_ci->c->topic_time; } else target_ci->last_topic_setter = source.owner->nick; FOREACH_MOD(I_OnChanRegistered, OnChanRegistered(target_ci)); source.Reply(_("All settings from \002%s\002 have been cloned to \002%s\002"), channel.c_str(), target.c_str()); } else if (what.equals_ci("ACCESS")) { for (unsigned i = 0; i < ci->GetAccessCount(); ++i) { ChanAccess *taccess = ci->GetAccess(i); AccessProvider *provider = taccess->provider; ChanAccess *newaccess = provider->Create(); newaccess->ci = target_ci; newaccess->mask = taccess->mask; newaccess->creator = taccess->creator; newaccess->last_seen = taccess->last_seen; newaccess->created = taccess->created; newaccess->Unserialize(taccess->Serialize()); target_ci->AddAccess(newaccess); } source.Reply(_("All access entries from \002%s\002 have been cloned to \002%s\002"), channel.c_str(), target.c_str()); } else if (what.equals_ci("AKICK")) { target_ci->ClearAkick(); for (unsigned i = 0; i < ci->GetAkickCount(); ++i) { AutoKick *akick = ci->GetAkick(i); if (akick->HasFlag(AK_ISNICK)) target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used); else target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used); } source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002"), channel.c_str(), target.c_str()); } else if (what.equals_ci("BADWORDS")) { target_ci->ClearBadWords(); for (unsigned i = 0; i < ci->GetBadWordCount(); ++i) { BadWord *bw = ci->GetBadWord(i); target_ci->AddBadWord(bw->word, bw->type); } source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002"), channel.c_str(), target.c_str()); } else { this->OnSyntaxError(source, ""); return; } Log(LOG_COMMAND, u, this, ci) << "to clone " << (what.empty() ? "everything from it" : what) << " to " << target_ci->name; 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); } } }