diff options
author | Adam <Adam@anope.org> | 2010-11-20 21:45:30 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2010-12-12 19:35:27 -0500 |
commit | 246f44b9888161aecefc81f0ff17ddd893287e3c (patch) | |
tree | b89607a9ad9c91914f292fc54cc32213a8d9f5c4 /src | |
parent | a85112172d842aa74aa5531788d383328d153e74 (diff) |
Added cs_mode, rewrote the old list mode code, and added CIDR support
Diffstat (limited to 'src')
-rw-r--r-- | src/actions.cpp | 21 | ||||
-rw-r--r-- | src/bots.cpp | 32 | ||||
-rw-r--r-- | src/channels.cpp | 820 | ||||
-rw-r--r-- | src/chanserv.cpp | 160 | ||||
-rw-r--r-- | src/config.cpp | 2 | ||||
-rw-r--r-- | src/language.cpp | 46 | ||||
-rw-r--r-- | src/misc.cpp | 80 | ||||
-rw-r--r-- | src/modes.cpp | 136 | ||||
-rw-r--r-- | src/operserv.cpp | 13 | ||||
-rw-r--r-- | src/regchannel.cpp | 186 | ||||
-rw-r--r-- | src/sockets.cpp | 74 | ||||
-rw-r--r-- | src/users.cpp | 25 | ||||
-rw-r--r-- | src/wildcard.cpp | 72 |
13 files changed, 663 insertions, 1004 deletions
diff --git a/src/actions.cpp b/src/actions.cpp index 4bb3563e5..6b3a96a24 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -71,28 +71,29 @@ void kill_user(const Anope::string &source, const Anope::string &user, const Ano */ void common_unban(ChannelInfo *ci, const Anope::string &nick) { - //uint32 ip = 0; - User *u; - Entry *ban, *next; - if (!ci || !ci->c || nick.empty()) return; - if (!(u = finduser(nick))) + User *u = finduser(nick); + if (!u) return; - if (!ci->c->bans || !ci->c->bans->count) + if (!ci->c->HasMode(CMODE_BAN)) return; if (ircd->svsmode_unban) ircdproto->SendBanDel(ci->c, nick); else - for (ban = ci->c->bans->entries; ban; ban = next) + { + std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = ci->c->GetModeList(CMODE_BAN); + for (; bans.first != bans.second;) { - next = ban->next; - if (entry_match(ban, u->nick, u->GetIdent(), u->host, /*ip XXX */ 0) || entry_match(ban, u->nick, u->GetIdent(), u->GetDisplayedHost(), /*ip XXX */0)) - ci->c->RemoveMode(NULL, CMODE_BAN, ban->mask); + Entry ban(bans.first->second); + ++bans.first; + if (ban.Matches(u)) + ci->c->RemoveMode(NULL, CMODE_BAN, ban.GetMask()); } + } } /*************************************************************************/ diff --git a/src/bots.cpp b/src/bots.cpp index 9b2cfddb6..3d57afe6e 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -141,28 +141,24 @@ void BotInfo::Join(Channel *c, bool update_ts) { if (Config->BSSmartJoin) { + std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = c->GetModeList(CMODE_BAN); + /* We check for bans */ - if (c->bans && c->bans->count) + for (; bans.first != bans.second; ++bans.first) { - Entry *ban, *next; - - for (ban = c->bans->entries; ban; ban = next) - { - next = ban->next; - - if (entry_match(ban, this->nick, this->GetIdent(), this->host, 0)) - c->RemoveMode(NULL, CMODE_BAN, ban->mask); - } + Entry ban(bans.first->second); + if (ban.Matches(this)) + c->RemoveMode(NULL, CMODE_BAN, ban.GetMask()); + } - Anope::string Limit; - unsigned limit = 0; - if (c->GetParam(CMODE_LIMIT, Limit) && Limit.is_pos_number_only()) - limit = convertTo<unsigned>(Limit); + Anope::string Limit; + unsigned limit = 0; + if (c->GetParam(CMODE_LIMIT, Limit) && Limit.is_pos_number_only()) + limit = convertTo<unsigned>(Limit); - /* Should we be invited? */ - if (c->HasMode(CMODE_INVITE) || (limit && c->users.size() >= limit)) - ircdproto->SendNoticeChanops(this, c, "%s invited %s into the channel.", this->nick.c_str(), this->nick.c_str()); - } + /* Should we be invited? */ + if (c->HasMode(CMODE_INVITE) || (limit && c->users.size() >= limit)) + ircdproto->SendNoticeChanops(this, c, "%s invited %s into the channel.", this->nick.c_str(), this->nick.c_str()); ModeManager::ProcessModes(); } diff --git a/src/channels.cpp b/src/channels.cpp index 72e573029..27d804c18 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -28,7 +28,6 @@ Channel::Channel(const Anope::string &nname, time_t ts) ChannelList[this->name] = this; this->creation_time = ts; - this->bans = this->excepts = this->invites = NULL; this->server_modetime = this->chanserv_modetime = 0; this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_time = 0; @@ -57,27 +56,12 @@ Channel::~Channel() if (this->ci) this->ci->c = NULL; - if (this->bans && this->bans->count) - while (this->bans->entries) - entry_delete(this->bans, this->bans->entries); - - if (ModeManager::FindChannelModeByName(CMODE_EXCEPT) && this->excepts && this->excepts->count) - while (this->excepts->entries) - entry_delete(this->excepts, this->excepts->entries); - - if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE) && this->invites && this->invites->count) - while (this->invites->entries) - entry_delete(this->invites, this->invites->entries); - ChannelList.erase(this->name); } void Channel::Reset() { - this->ClearModes(NULL, false); - this->ClearBans(NULL, false); - this->ClearExcepts(NULL, false); - this->ClearInvites(NULL, false); + this->modes.clear(); for (CUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it) { @@ -294,11 +278,27 @@ bool Channel::HasUserStatus(User *u, ChannelModeName Name) const /** * See if a channel has a mode * @param Name The mode name - * @return true or false + * @param param The optional mode param + * @return The number of modes set */ -bool Channel::HasMode(ChannelModeName Name) const +size_t Channel::HasMode(ChannelModeName Name, const Anope::string ¶m) { - return modes.HasFlag(Name); + if (param.empty()) + return modes.count(Name); + std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(Name); + for (; its.first != its.second; ++its.first) + if (its.first->second == param) + return 1; + return 0; +} + +/** Get a list of modes on a channel + * @param Name A mode name to get the list of + * @return a pair of iterators for the beginning and end of the list + */ +std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> Channel::GetModeList(ChannelModeName Name) +{ + return std::make_pair(this->modes.find(Name), this->modes.upper_bound(Name)); } /** Set a mode internally on a channel, this is not sent out to the IRCd @@ -346,36 +346,21 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool chan_set_correct_modes(u, this, 0); return; } - /* Setting b/e/I etc */ - else if (cm->Type == MODE_LIST) - { - if (param.empty()) - { - Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; - return; - } - ChannelModeList *cml = debug_cast<ChannelModeList *>(cm); - cml->AddMask(this, param); + if (cm->Type != MODE_LIST) + this->modes.erase(cm->Name); + this->modes.insert(std::make_pair(cm->Name, param)); + + if (param.empty() && cm->Type != MODE_REGULAR) + { + Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " for " << this->name << " with a paramater, but its not a param mode"; return; } - modes.SetFlag(cm->Name); - - if (!param.empty()) + if (cm->Type == MODE_LIST) { - if (cm->Type != MODE_PARAM) - { - Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " for " << this->name << " with a paramater, but its not a param mode"; - return; - } - - /* They could be resetting the mode to change its params */ - std::map<ChannelModeName, Anope::string>::iterator it = Params.find(cm->Name); - if (it != Params.end()) - Params.erase(it); - - Params.insert(std::make_pair(cm->Name, param)); + ChannelModeList *cml = debug_cast<ChannelModeList *>(cm); + cml->OnAdd(this, param); } /* Channel mode +P or so was set, mark this channel as persistant */ @@ -398,33 +383,34 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool if (!ci) return; - /* If this channel has this mode locked negative */ - if (ci->HasMLock(cm->Name, false)) + ModeLock *ml = ci->GetMLock(cm->Name, param); + if (ml) { - /* Remove the mode */ - if (cm->Type == MODE_PARAM) + if (ml->set && cm->Type == MODE_PARAM) { Anope::string cparam; - GetParam(cm->Name, cparam); - RemoveMode(NULL, cm, cparam); + this->GetParam(cm->Name, cparam); + + /* We have the wrong param set */ + if (cparam.empty() || ml->param.empty() || !cparam.equals_cs(ml->param)) + /* Reset the mode with the correct param */ + this->SetMode(NULL, cm, ml->param); + } + else if (!ml->set) + { + if (cm->Type == MODE_REGULAR) + this->RemoveMode(NULL, cm); + else if (cm->Type == MODE_PARAM) + { + Anope::string cparam; + this->GetParam(cm->Name, cparam); + this->RemoveMode(NULL, cm, cparam); + } + else if (cm->Type == MODE_LIST) + { + this->RemoveMode(NULL, cm, param); + } } - else if (cm->Type == MODE_REGULAR) - RemoveMode(NULL, cm); - } - /* If this is a param mode and its mlocked +, check to ensure someone didn't reset it with the wrong param */ - else if (cm->Type == MODE_PARAM && ci->HasMLock(cm->Name, true)) - { - ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm); - Anope::string cparam, ciparam; - /* Get the param currently set on this channel */ - GetParam(cmp->Name, cparam); - /* Get the param set in mlock */ - ci->GetParam(cmp->Name, ciparam); - - /* We have the wrong param set */ - if (cparam.empty() || ciparam.empty() || !cparam.equals_cs(ciparam)) - /* Reset the mode with the correct param */ - SetMode(NULL, cm, ciparam); } } @@ -475,29 +461,29 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo this->SetMode(bi, cm, bi->nick); } + /* Enforce secureops, etc */ + if (EnforceMLock) + chan_set_correct_modes(u, this, 1); return; } - /* Setting b/e/I etc */ - else if (cm->Type == MODE_LIST) - { - if (param.empty()) - { - Log() << "Channel::RemoveModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; - return; - } - ChannelModeList *cml = debug_cast<ChannelModeList *>(cm); - cml->DelMask(this, param); - return; + if (cm->Type == MODE_LIST && !param.empty()) + { + std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(cm->Name); + for (; its.first != its.second; ++its.first) + if (Anope::Match(param, its.first->second)) + { + this->modes.erase(its.first); + break; + } } - - modes.UnsetFlag(cm->Name); - - if (cm->Type == MODE_PARAM) + else + this->modes.erase(cm->Name); + + if (cm->Type == MODE_LIST) { - std::map<ChannelModeName, Anope::string>::iterator it = Params.find(cm->Name); - if (it != Params.end()) - Params.erase(it); + ChannelModeList *cml = debug_cast<ChannelModeList *>(cm); + cml->OnDel(this, param); } if (cm->Name == CMODE_PERM) @@ -525,22 +511,14 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo if (!ci || !EnforceMLock || MOD_RESULT == EVENT_STOP) return; + ModeLock *ml = ci->GetMLock(cm->Name, param); /* This channel has this the mode locked on */ - if (ci->HasMLock(cm->Name, true)) + if (ml && ml->set) { if (cm->Type == MODE_REGULAR) - { - /* Set the mode */ - SetMode(NULL, cm); - } - /* This is a param mode */ - else if (cm->Type == MODE_PARAM) - { - Anope::string cparam; - /* Get the param stored in mlock for this mode */ - if (ci->GetParam(cm->Name, cparam)) - SetMode(NULL, cm, cparam); - } + this->SetMode(NULL, cm); + else if (cm->Type == MODE_PARAM || cm->Type == MODE_LIST) + this->SetMode(NULL, cm, ml->param); } } @@ -557,8 +535,12 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m, /* Don't set modes already set */ if (cm->Type == MODE_REGULAR && HasMode(cm->Name)) return; - else if (cm->Type == MODE_PARAM && HasMode(cm->Name)) + else if (cm->Type == MODE_PARAM) { + ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm); + if (!cmp->IsValid(param)) + return; + Anope::string cparam; if (GetParam(cm->Name, cparam) && cparam.equals_cs(param)) return; @@ -571,7 +553,9 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m, } else if (cm->Type == MODE_LIST) { - // XXX this needs rewritten + ChannelModeList *cml = debug_cast<ChannelModeList *>(cm); + if (this->HasMode(cm->Name, param) || !cml->IsValid(param)) + return; } ModeManager::StackerAdd(bi, this, cm, true, param); @@ -612,20 +596,22 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶ } else if (cm->Type == MODE_LIST) { - // XXX this needs to be rewritten sometime + if (!this->HasMode(cm->Name, param)) + return; } - /* If this mode needs no param when being unset, empty the param */ - bool SendParam = true; + /* Get the param to send, if we need it */ + Anope::string realparam = param; if (cm->Type == MODE_PARAM) { + realparam.clear(); ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm); - if (cmp->MinusNoArg) - SendParam = false; + if (!cmp->MinusNoArg) + this->GetParam(cmp->Name, realparam); } - ModeManager::StackerAdd(bi, this, cm, false, param); - RemoveModeInternal(cm, SendParam ? param : "", EnforceMLock); + ModeManager::StackerAdd(bi, this, cm, false, realparam); + RemoveModeInternal(cm, realparam, EnforceMLock); } /** @@ -647,11 +633,11 @@ void Channel::RemoveMode(BotInfo *bi, ChannelModeName Name, const Anope::string */ bool Channel::GetParam(ChannelModeName Name, Anope::string &Target) const { - std::map<ChannelModeName, Anope::string>::const_iterator it = Params.find(Name); + std::multimap<ChannelModeName, Anope::string>::const_iterator it = this->modes.find(Name); Target.clear(); - if (it != Params.end()) + if (it != this->modes.end()) { Target = it->second; return true; @@ -660,121 +646,8 @@ bool Channel::GetParam(ChannelModeName Name, Anope::string &Target) const return false; } -/** Check if a mode is set and has a param - * @param Name The mode - */ -bool Channel::HasParam(ChannelModeName Name) const -{ - std::map<ChannelModeName, Anope::string>::const_iterator it = Params.find(Name); - - if (it != Params.end()) - return true; - - return false; -} - /*************************************************************************/ -/** Clear all the modes from the channel - * @param bi The client setting the modes - * @param internal Only remove the modes internally - */ -void Channel::ClearModes(BotInfo *bi, bool internal) -{ - for (size_t n = CMODE_BEGIN + 1; n != CMODE_END; ++n) - { - ChannelMode *cm = ModeManager::FindChannelModeByName(static_cast<ChannelModeName>(n)); - - if (cm && this->HasMode(cm->Name)) - { - if (cm->Type == MODE_REGULAR) - { - if (!internal) - this->RemoveMode(NULL, cm); - else - this->RemoveModeInternal(cm); - } - else if (cm->Type == MODE_PARAM) - { - Anope::string param; - this->GetParam(cm->Name, param); - if (!internal) - this->RemoveMode(NULL, cm, param); - else - this->RemoveModeInternal(cm, param); - } - } - } - - modes.ClearFlags(); -} - -/** Clear all the bans from the channel - * @param bi The client setting the modes - * @param internal Only remove the modes internally - */ -void Channel::ClearBans(BotInfo *bi, bool internal) -{ - Entry *entry, *nexte; - - ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_BAN)); - - if (cml && this->bans && this->bans->count) - for (entry = this->bans->entries; entry; entry = nexte) - { - nexte = entry->next; - - if (!internal) - this->RemoveMode(bi, cml, entry->mask); - else - this->RemoveModeInternal(cml, entry->mask); - } -} - -/** Clear all the excepts from the channel - * @param bi The client setting the modes - * @param internal Only remove the modes internally - */ -void Channel::ClearExcepts(BotInfo *bi, bool internal) -{ - Entry *entry, *nexte; - - ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_EXCEPT)); - - if (cml && this->excepts && this->excepts->count) - for (entry = this->excepts->entries; entry; entry = nexte) - { - nexte = entry->next; - - if (!internal) - this->RemoveMode(bi, cml, entry->mask); - else - this->RemoveModeInternal(cml, entry->mask); - } -} - -/** Clear all the invites from the channel - * @param bi The client setting the modes - * @param internal Only remove the modes internally - */ -void Channel::ClearInvites(BotInfo *bi, bool internal) -{ - Entry *entry, *nexte; - - ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)); - - if (cml && this->invites && this->invites->count) - for (entry = this->invites->entries; entry; entry = nexte) - { - nexte = entry->next; - - if (!internal) - this->RemoveMode(bi, cml, entry->mask); - else - this->RemoveModeInternal(cml, entry->mask); - } -} - /** Set a string of modes on the channel * @param bi The client setting the modes * @param EnforceMLock Should mlock be enforced on this mode change @@ -980,45 +853,26 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...) Anope::string Channel::GetModes(bool complete, bool plus) { - Anope::string res; + Anope::string res, params; - if (this->HasModes()) + for (std::multimap<ChannelModeName, Anope::string>::const_iterator it = this->modes.begin(), it_end = this->modes.end(); it != it_end; ++it) { - Anope::string params; - for (std::map<Anope::string, Mode *>::const_iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it) - { - if (it->second->Class != MC_CHANNEL) - continue; + ChannelMode *cm = ModeManager::FindChannelModeByName(it->first); + if (!cm || cm->Type == MODE_LIST) + continue; - ChannelMode *cm = debug_cast<ChannelMode *>(it->second); + res += cm->ModeChar; - if (this->HasMode(cm->Name)) - { - res += cm->ModeChar; + if (complete && !it->second.empty()) + { + ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm); - if (complete) - { - if (cm->Type == MODE_PARAM) - { - ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm); - - if (plus || !cmp->MinusNoArg) - { - Anope::string param; - this->GetParam(cmp->Name, param); - - if (!param.empty()) - params += " " + param; - } - } - } - } + if (plus || !cmp->MinusNoArg) + params += " " + it->second; } - - res += params; } - return res; + return res + params; } void Channel::ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts) @@ -1083,17 +937,6 @@ void get_channel_stats(long *nrec, long *memuse) mem += sizeof(*chan); if (!chan->topic.empty()) mem += chan->topic.length() + 1; - if (chan->GetParam(CMODE_KEY, buf)) - mem += buf.length() + 1; - if (chan->GetParam(CMODE_FLOOD, buf)) - mem += buf.length() + 1; - if (chan->GetParam(CMODE_REDIRECT, buf)) - mem += buf.length() + 1; - mem += get_memuse(chan->bans); - if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) - mem += get_memuse(chan->excepts); - if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)) - mem += get_memuse(chan->invites); for (CUserList::iterator it = chan->users.begin(), it_end = chan->users.end(); it != it_end; ++it) { mem += sizeof(*it); @@ -1355,6 +1198,26 @@ void chan_set_correct_modes(User *user, Channel *c, int give_modes) if (halfop && c->HasUserStatus(user, CMODE_HALFOP) && !check_access(user, ci, CA_AUTOHALFOP) && !check_access(user, ci, CA_HALFOPME)) c->RemoveMode(NULL, CMODE_HALFOP, user->nick); } + + // Check mlock + for (std::multimap<ChannelModeName, ModeLock>::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) + { + const ModeLock &ml = it->second; + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm || cm->Type != MODE_STATUS) + continue; + + if (Anope::Match(user->nick, ml.param) || Anope::Match(user->GetDisplayedMask(), ml.param)) + { + if ((ml.set && !c->HasUserStatus(user, ml.name)) || (!ml.set && c->HasUserStatus(user, ml.name))) + { + if (ml.set && give_modes) + c->SetMode(NULL, cm, user->nick, false); + else if (!ml.set && !give_modes) + c->RemoveMode(NULL, cm, user->nick, false); + } + } + } } /*************************************************************************/ @@ -1376,382 +1239,137 @@ void MassChannelModes(BotInfo *bi, const Anope::string &modes) } } -/*************************************************************************/ - -/** - * This handles creating a new Entry. - * This function destroys and free's the given mask as a side effect. - * @param mask Host/IP/CIDR mask to convert to an entry - * @return Entry struct for the given mask, NULL if creation failed +/** Constructor + * @param _host A full nick!ident@host/cidr mask */ -Entry *entry_create(const Anope::string &mask) +Entry::Entry(const Anope::string &_host) { - Entry *entry; - Anope::string cidrhost; - uint32 ip, cidr; - - entry = new Entry; - entry->SetFlag(ENTRYTYPE_NONE); - entry->prev = NULL; - entry->next = NULL; - entry->mask = mask; - - Anope::string newmask = mask, host, nick, user; + this->SetFlag(ENTRYTYPE_NONE); + this->cidr_len = 0; + this->mask = _host; - size_t at = newmask.find('@'); + Anope::string _nick, _user, _realhost; + size_t at = _host.find('@'); if (at != Anope::string::npos) { - host = newmask.substr(at + 1); - newmask = newmask.substr(0, at); - /* If the user is purely a wildcard, ignore it */ - if (!str_is_pure_wildcard(newmask)) + _realhost = _host.substr(at + 1); + Anope::string _nickident = _host.substr(0, at); + + size_t ex = _nickident.find('!'); + if (ex != Anope::string::npos) { - /* There might be a nick too */ - //user = strchr(mask, '!'); - size_t ex = newmask.find('!'); - if (ex != Anope::string::npos) - { - user = newmask.substr(ex + 1); - newmask = newmask.substr(0, ex); - /* If the nick is purely a wildcard, ignore it */ - if (!str_is_pure_wildcard(newmask)) - nick = newmask; - } - else - user = newmask; + _user = _nickident.substr(ex + 1); + _nick = _nickident.substr(0, ex); } + else + _user = _nickident; } else - /* It is possibly an extended ban/invite mask, but we do - * not support these at this point.. ~ Viper */ - /* If there's no user in the mask, assume a pure wildcard */ - host = newmask; - - if (!nick.empty()) + _realhost = _host; + + if (!_nick.empty() && !str_is_pure_wildcard(_nick)) { - entry->nick = nick; - /* Check if we have a wildcard user */ - if (str_is_wildcard(nick)) - entry->SetFlag(ENTRYTYPE_NICK_WILD); + this->nick = _nick; + if (str_is_wildcard(_nick)) + this->SetFlag(ENTRYTYPE_NICK_WILD); else - entry->SetFlag(ENTRYTYPE_NICK); + this->SetFlag(ENTRYTYPE_NICK); } - if (!user.empty()) + if (!_user.empty() && !str_is_pure_wildcard(_user)) { - entry->user = user; - /* Check if we have a wildcard user */ - if (str_is_wildcard(user)) - entry->SetFlag(ENTRYTYPE_USER_WILD); + this->user = _user; + if (str_is_wildcard(_user)) + this->SetFlag(ENTRYTYPE_USER_WILD); else - entry->SetFlag(ENTRYTYPE_USER); + this->SetFlag(ENTRYTYPE_USER); } - /* Only check the host if it's not a pure wildcard */ - if (!host.empty() && !str_is_pure_wildcard(host)) + if (!_realhost.empty() && !str_is_pure_wildcard(_realhost)) { - if (ircd->cidrchanbei && str_is_cidr(host, ip, cidr, cidrhost)) - { - entry->cidr_ip = ip; - entry->cidr_mask = cidr; - entry->SetFlag(ENTRYTYPE_CIDR4); - host = cidrhost; - } - else if (ircd->cidrchanbei && host.find('/') != Anope::string::npos) + size_t sl = _realhost.find_last_of('/'); + if (sl != Anope::string::npos) { - /* Most IRCd's don't enforce sane bans therefore it is not - * so unlikely we will encounter this. - * Currently we only support strict CIDR without taking into - * account quirks of every single ircd (nef) that ignore everything - * after the first /cidr. To add this, sanitaze before sending to - * str_is_cidr() as this expects a standard cidr. - * Add it to the internal list (so it is included in for example clear) - * but do not use if during matching.. ~ Viper */ - entry->ClearFlags(); - entry->SetFlag(ENTRYTYPE_NONE); - } - else - { - entry->host = host; - if (str_is_wildcard(host)) - entry->SetFlag(ENTRYTYPE_HOST_WILD); - else - entry->SetFlag(ENTRYTYPE_HOST); - } - } - - return entry; -} - -/** - * Create an entry and add it at the beginning of given list. - * @param list The List the mask should be added to - * @param mask The mask to parse and add to the list - * @return Pointer to newly added entry. NULL if it fails. - */ -Entry *entry_add(EList *list, const Anope::string &mask) -{ - Entry *e; - - e = entry_create(mask); - - if (!e) - return NULL; - - e->next = list->entries; - e->prev = NULL; - - if (list->entries) - list->entries->prev = e; - list->entries = e; - ++list->count; - - return e; -} - -/** - * Delete the given entry from a given list. - * @param list Linked list from which entry needs to be removed. - * @param e The entry to be deleted, must be member of list. - */ -void entry_delete(EList *list, Entry *e) -{ - if (!list || !e) - return; - - if (e->next) - e->next->prev = e->prev; - if (e->prev) - e->prev->next = e->next; - - if (list->entries == e) - list->entries = e->next; - - delete e; - - --list->count; -} - -/** - * Create and initialize a new entrylist - * @return Pointer to the created EList object - **/ -EList *list_create() -{ - EList *list; - - list = new EList; - list->entries = NULL; - list->count = 0; - - return list; -} - -/** - * Match the given Entry to the given user/host and optional IP addy - * @param e Entry struct to match against - * @param nick Nick to match against - * @param user User to match against - * @param host Host to match against - * @param ip IP to match against, set to 0 to not match this - * @return 1 for a match, 0 for no match - */ -int entry_match(Entry *e, const Anope::string &nick, const Anope::string &user, const Anope::string &host, uint32 ip) -{ - /* If we don't get an entry, or it s an invalid one, no match ~ Viper */ - if (!e || !e->FlagCount()) - return 0; - - if (ircd->cidrchanbei && e->HasFlag(ENTRYTYPE_CIDR4) && (!ip || (ip && (ip & e->cidr_mask) != e->cidr_ip))) - return 0; - if (e->HasFlag(ENTRYTYPE_NICK) && (nick.empty() || !e->nick.equals_ci(nick))) - return 0; - if (e->HasFlag(ENTRYTYPE_USER) && (user.empty() || !e->user.equals_ci(user))) - return 0; - if (e->HasFlag(ENTRYTYPE_HOST) && (host.empty() || !e->host.equals_ci(host))) - return 0; - if (e->HasFlag(ENTRYTYPE_NICK_WILD) && !Anope::Match(nick, e->nick)) - return 0; - if (e->HasFlag(ENTRYTYPE_USER_WILD) && !Anope::Match(user, e->user)) - return 0; - if (e->HasFlag(ENTRYTYPE_HOST_WILD) && !Anope::Match(host, e->host)) - return 0; - - return 1; -} - -/** - * Match the given Entry to the given hostmask and optional IP addy. - * @param e Entry struct to match against - * @param mask Hostmask to match against - * @param ip IP to match against, set to 0 to not match this - * @return 1 for a match, 0 for no match - */ -int entry_match_mask(Entry *e, const Anope::string &mask, uint32 ip) -{ - int res; - - Anope::string hostmask = mask, host, user, nick; + try + { + sockaddrs addr; + bool ipv6 = _realhost.substr(0, sl).find(':') != Anope::string::npos; + addr.pton(ipv6 ? AF_INET6 : AF_INET, _realhost.substr(0, sl)); + /* If we got here, _realhost is a valid IP */ - size_t at = hostmask.find('@'); - if (at != Anope::string::npos) - { - host = hostmask.substr(at + 1); - hostmask = hostmask.substr(0, at); - size_t ex = hostmask.find('!'); - if (ex != Anope::string::npos) - { - user = hostmask.substr(ex + 1); - nick = hostmask.substr(0, ex); + Anope::string cidr_range = _realhost.substr(sl + 1); + if (cidr_range.is_pos_number_only()) + { + _realhost = _realhost.substr(0, sl); + this->cidr_len = convertTo<unsigned int>(cidr_range); + this->SetFlag(ENTRYTYPE_CIDR); + Log(LOG_DEBUG) << "Ban " << _realhost << " has cidr " << static_cast<unsigned int>(this->cidr_len); + } + } + catch (const SocketException &) { } } - else - user = hostmask; - } - else - host = hostmask; - - res = entry_match(e, nick, user, host, ip); - - return res; -} - -/** - * Match a nick, user, host, and ip to a list entry - * @param e List that should be matched against - * @param nick The nick to match - * @param user The user to match - * @param host The host to match - * @param ip The ip to match - * @return Returns the first matching entry, if none, NULL is returned. - */ -Entry *elist_match(EList *list, const Anope::string &nick, const Anope::string &user, const Anope::string &host, uint32 ip) -{ - Entry *e; - - if (!list || !list->entries) - return NULL; - - for (e = list->entries; e; e = e->next) - if (entry_match(e, nick, user, host, ip)) - return e; - - /* We matched none */ - return NULL; -} -/** - * Match a mask and ip to a list. - * @param list EntryList that should be matched against - * @param mask The nick!user@host mask to match - * @param ip The ip to match - * @return Returns the first matching entry, if none, NULL is returned. - */ -Entry *elist_match_mask(EList *list, const Anope::string &mask, uint32 ip) -{ - Entry *res; - - if (!list || !list->entries || mask.empty()) - return NULL; + this->host = _realhost; - Anope::string hostmask = mask, host, user, nick; - - size_t at = hostmask.find('@'); - if (at != Anope::string::npos) - { - host = hostmask.substr(at + 1); - hostmask = hostmask.substr(0, at); - size_t ex = hostmask.find('!'); - if (ex != Anope::string::npos) + if (!this->HasFlag(ENTRYTYPE_CIDR)) { - user = hostmask.substr(ex + 1); - nick = hostmask.substr(0, ex); + if (str_is_wildcard(_realhost)) + this->SetFlag(ENTRYTYPE_HOST_WILD); + else + this->SetFlag(ENTRYTYPE_HOST); } - else - user = hostmask; } - else - host = hostmask; - - res = elist_match(list, nick, user, host, ip); - - return res; } -/** - * Check if a user matches an entry on a list. - * @param list EntryList that should be matched against - * @param user The user to match against the entries - * @return Returns the first matching entry, if none, NULL is returned. +/** Get the banned mask for this entry + * @return The mask */ -Entry *elist_match_user(EList *list, User *u) +const Anope::string Entry::GetMask() { - Entry *res; - //uint32 ip = 0; - - if (!list || !list->entries || !u) - return NULL; - - /* Match what we ve got against the lists.. */ - res = elist_match(list, u->nick, u->GetIdent(), u->host, /*ip XXX*/0); - if (!res) - res = elist_match(list, u->nick, u->GetIdent(), u->GetDisplayedHost(), /*ip XXX*/0); - if (!res && !u->GetCloakedHost().empty() && !u->GetCloakedHost().equals_cs(u->GetDisplayedHost())) - res = elist_match(list, u->nick, u->GetIdent(), u->GetCloakedHost(), /*ip XXX*/ 0); - - return res; + return this->mask; } -/** - * Find a entry identical to the given mask.. - * @param list EntryList that should be matched against - * @param mask The *!*@* mask to match - * @return Returns the first matching entry, if none, NULL is returned. - */ -Entry *elist_find_mask(EList *list, const Anope::string &mask) -{ - Entry *e; - - if (!list || !list->entries || mask.empty()) - return NULL; - - for (e = list->entries; e; e = e->next) - if (e->mask.equals_ci(mask)) - return e; - - return NULL; -} - -/** - * Gets the total memory use of an entrylit. - * @param list The list we should estimate the mem use of. - * @return Returns the memory useage of the given list. +/** Check if this entry matches a user + * @param u The user + * @return true on match */ -long get_memuse(EList *list) +bool Entry::Matches(User *u) const { - Entry *e; - long mem = 0; - - if (!list) + if (!this->FlagCount()) return 0; + + Anope::string _nick = u->nick; + Anope::string _user = u->GetVIdent(); + Anope::string _host = u->GetDisplayedHost(); - mem += sizeof(EList *); - mem += sizeof(Entry *) * list->count; - if (list->entries) + if (this->HasFlag(ENTRYTYPE_CIDR)) { - for (e = list->entries; e; e = e->next) + try + { + cidr cidr_mask(this->host, this->cidr_len); + if (!u->ip() || !cidr_mask.match(u->ip)) + { + return false; + } + } + catch (const SocketException &) { - if (!e->nick.empty()) - mem += e->nick.length() + 1; - if (!e->user.empty()) - mem += e->user.length() + 1; - if (!e->host.empty()) - mem += e->host.length() + 1; - if (!e->mask.empty()) - mem += e->mask.length() + 1; + return false; } } + if (this->HasFlag(ENTRYTYPE_NICK) && (_nick.empty() || !this->nick.equals_ci(_nick))) + return false; + if (this->HasFlag(ENTRYTYPE_USER) && (_user.empty() || !this->user.equals_ci(_user))) + return false; + if (this->HasFlag(ENTRYTYPE_HOST) && (_host.empty() || !this->host.equals_ci(_host))) + return false; + if (this->HasFlag(ENTRYTYPE_NICK_WILD) && !Anope::Match(_nick, this->nick)) + return false; + if (this->HasFlag(ENTRYTYPE_USER_WILD) && !Anope::Match(_user, this->user)) + return false; + if (this->HasFlag(ENTRYTYPE_HOST_WILD) && !Anope::Match(_host, this->host)) + return false; - return mem; + return true; } -/*************************************************************************/ diff --git a/src/chanserv.cpp b/src/chanserv.cpp index ca37f0cc7..ef3de90cd 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -24,7 +24,6 @@ static int def_levels[][2] = { { CA_INVITE, 5 }, { CA_AKICK, 10 }, { CA_SET, ACCESS_QOP }, - { CA_CLEAR, ACCESS_FOUNDER }, { CA_UNBAN, 5 }, { CA_OPDEOP, 5 }, { CA_ACCESS_LIST, 1 }, @@ -52,6 +51,7 @@ static int def_levels[][2] = { { CA_BANME, 5 }, { CA_BAN, 5 }, { CA_TOPIC, ACCESS_FOUNDER }, + { CA_MODE, ACCESS_FOUNDER }, { CA_INFO, ACCESS_QOP }, { CA_AUTOOWNER, ACCESS_QOP }, { CA_OWNER, ACCESS_FOUNDER }, @@ -74,7 +74,6 @@ LevelInfo levelinfo[] = { { CA_SET, "SET", CHAN_LEVEL_SET }, { CA_BAN, "BAN", CHAN_LEVEL_BAN }, { CA_BANME, "BANME", CHAN_LEVEL_BANME }, - { CA_CLEAR, "CLEAR", CHAN_LEVEL_CLEAR }, { CA_GETKEY, "GETKEY", CHAN_LEVEL_GETKEY }, { CA_HALFOP, "HALFOP", CHAN_LEVEL_HALFOP }, { CA_HALFOPME, "HALFOPME", CHAN_LEVEL_HALFOPME }, @@ -87,6 +86,7 @@ LevelInfo levelinfo[] = { { CA_PROTECT, "PROTECT", CHAN_LEVEL_PROTECT }, { CA_PROTECTME, "PROTECTME", CHAN_LEVEL_PROTECTME }, { CA_TOPIC, "TOPIC", CHAN_LEVEL_TOPIC }, + { CA_MODE, "MODE", CHAN_LEVEL_MODE }, { CA_UNBAN, "UNBAN", CHAN_LEVEL_UNBAN }, { CA_VOICE, "VOICE", CHAN_LEVEL_VOICE }, { CA_VOICEME, "VOICEME", CHAN_LEVEL_VOICEME }, @@ -111,59 +111,30 @@ int levelinfo_maxwidth = 0; Anope::string get_mlock_modes(ChannelInfo *ci, int complete) { - ChannelMode *cm; - ChannelModeParam *cmp; - std::map<char, ChannelMode *>::iterator it, it_end; - Anope::string res, param; + Anope::string pos = "+", neg = "-", params; - if (ci->GetMLockCount(true) || ci->GetMLockCount(false)) + for (std::map<ChannelModeName, ModeLock>::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) { - if (ci->GetMLockCount(true)) - { - res += '+'; - - for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) - { - cm = it->second; - - if (ci->HasMLock(cm->Name, true)) - res += it->first; - } - } - - if (ci->GetMLockCount(false)) - { - res += '-'; - - for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) - { - cm = it->second; - - if (ci->HasMLock(cm->Name, false)) - res += it->first; - } - } - - if (ci->GetMLockCount(true) && complete) - { - for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) - { - cm = it->second; - - if (cm->Type == MODE_PARAM) - { - cmp = debug_cast<ChannelModeParam *>(cm); - - ci->GetParam(cmp->Name, param); - - if (!param.empty()) - res += " " + param; - } - } - } + const ModeLock &ml = it->second; + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm) + continue; + + if (ml.set) + pos += cm->ModeChar; + else + neg += cm->ModeChar; + + if (complete && !ml.param.empty() && (cm->Type == MODE_PARAM || cm->Type == MODE_LIST)) + params += " " + ml.param; } - return res; + if (pos.length() == 1) + pos.clear(); + if (neg.length() == 1) + neg.clear(); + + return pos + neg + params; } /*************************************************************************/ @@ -173,7 +144,7 @@ Anope::string get_mlock_modes(ChannelInfo *ci, int complete) void get_chanserv_stats(long *nrec, long *memuse) { long count = 0, mem = 0; - Anope::string param; + ModeLock *ml; for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it) { @@ -186,14 +157,17 @@ void get_chanserv_stats(long *nrec, long *memuse) mem += ci->GetAccessCount() * sizeof(ChanAccess); mem += ci->GetAkickCount() * sizeof(AutoKick); - if (ci->GetParam(CMODE_KEY, param)) - mem += param.length() + 1; + ml = ci->GetMLock(CMODE_KEY); + if (ml && !ml->param.empty()) + mem += ml->param.length() + 1; - if (ci->GetParam(CMODE_FLOOD, param)) - mem += param.length() + 1; + ml = ci->GetMLock(CMODE_FLOOD); + if (ml && !ml->param.empty()) + mem += ml->param.length() + 1; - if (ci->GetParam(CMODE_REDIRECT, param)) - mem += param.length() + 1; + ml = ci->GetMLock(CMODE_REDIRECT); + if (ml && !ml->param.empty()) + mem += ml->param.length() + 1; if (!ci->last_topic.empty()) mem += ci->last_topic.length() + 1; @@ -237,11 +211,6 @@ void cs_init() void check_modes(Channel *c) { - ChannelInfo *ci; - ChannelMode *cm; - std::map<char, ChannelMode *>::iterator it, it_end; - Anope::string param, ciparam; - if (!c) { Log() << "check_modes called with NULL values"; @@ -268,61 +237,52 @@ void check_modes(Channel *c) c->chanserv_modecount++; /* Check if the channel is registered; if not remove mode -r */ - if (!(ci = c->ci)) + ChannelInfo *ci = c->ci; + if (!ci) { if (c->HasMode(CMODE_REGISTERED)) c->RemoveMode(NULL, CMODE_REGISTERED); return; } - for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) + for (std::map<ChannelModeName, ModeLock>::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) { - cm = it->second; + const ModeLock &ml = it->second; + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm) + continue; - /* If this channel does not have the mode and the mode is mlocked */ - if (cm->Type == MODE_REGULAR && !c->HasMode(cm->Name) && ci->HasMLock(cm->Name, true)) + if (cm->Type == MODE_REGULAR) { - /* Add the eventual parameter and modify the Channel structure */ - if (cm->Type == MODE_PARAM) - { - if (ci->GetParam(cm->Name, ciparam)) - c->SetMode(NULL, cm, ciparam); - } - else + if (!c->HasMode(cm->Name) && ml.set) c->SetMode(NULL, cm); + else if (c->HasMode(cm->Name) && !ml.set) + c->RemoveMode(NULL, cm); } - /* If this is a param mode and its mlocked, check to ensure it is set and set to the correct value */ - else if (cm->Type == MODE_PARAM && ci->HasMLock(cm->Name, true)) + else if (cm->Type == MODE_PARAM) { + Anope::string param; c->GetParam(cm->Name, param); - ci->GetParam(cm->Name, ciparam); /* If the channel doesnt have the mode, or it does and it isn't set correctly */ - if (!c->HasMode(cm->Name) || (!param.empty() && !ciparam.empty() && !param.equals_cs(ciparam))) - c->SetMode(NULL, cm, ciparam); - } - } - - for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) - { - cm = it->second; - - /* If the channel has the mode */ - if (c->HasMode(cm->Name) && ci->HasMLock(cm->Name, false)) - { - /* Add the eventual parameter */ - if (cm->Type == MODE_PARAM) + if (ml.set) { - ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm); - - if (!cmp->MinusNoArg) - { - if (c->GetParam(cmp->Name, param)) - c->RemoveMode(NULL, cm, param); - } + if (!c->HasMode(cm->Name) || (!param.empty() && !ml.param.empty() && !param.equals_cs(ml.param))) + c->SetMode(NULL, cm, ml.param); } else - c->RemoveMode(NULL, cm); + { + if (c->HasMode(cm->Name)) + c->RemoveMode(NULL, cm); + } + + } + else if (cm->Type == MODE_LIST) // XXX we still need better list code... + { + if (ml.set) + c->SetMode(NULL, cm, ml.param); + else + c->RemoveMode(NULL, cm, ml.param); } } } diff --git a/src/config.cpp b/src/config.cpp index 818021efb..6dddd7691 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -167,7 +167,7 @@ ServerConfig::ServerConfig() : errstr(""), config_data() } } - this->WallOper = this->WallBadOS = this->WallOSGlobal = this->WallOSMode = this->WallOSClearmodes = this->WallOSKick = this->WallOSAkill = this->WallOSSNLine = this->WallOSSQLine = + this->WallOper = this->WallBadOS = this->WallOSGlobal = this->WallOSMode = this->WallOSKick = this->WallOSAkill = this->WallOSSNLine = this->WallOSSQLine = this->WallOSSZLine = this->WallOSNoOp = this->WallOSJupe = this->WallAkillExpire = this->WallSNLineExpire = this->WallSQLineExpire = this->WallSZLineExpire = this->WallExceptionExpire = this->WallGetpass = this->WallSetpass = this->WallForbid = this->WallDrop = false; if (!OSNotifications.empty()) diff --git a/src/language.cpp b/src/language.cpp index 3ef010034..31eb1f1f8 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -769,6 +769,8 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("Allowed to use BAN command"), /* CHAN_LEVEL_TOPIC */ _("Allowed to use TOPIC command"), + /* CHAN_LEVEL_MODE */ + _("Allowed to use MODE command"), /* CHAN_LEVEL_INFO */ _("Allowed to use INFO command with ALL option"), /* CHAN_LEVEL_AUTOOWNER */ @@ -1294,8 +1296,10 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("%s has been unbanned from %s."), /* CHAN_TOPIC_SYNTAX */ _("TOPIC channel [topic]"), - /* CHAN_CLEARUSERS */ + /* CHAN_CLEARUSERS_SYNTAX */ _("CLEARUSERS \037channel\037"), + /* CHAN_CLEARED_USERS */ + _("All users have been kicked from \2%s\2."), /* CHAN_CLONED */ _("All settings from \002%s\002 have been transferred to \002%s\002"), /* CHAN_CLONED_ACCESS */ @@ -1366,6 +1370,24 @@ const char *const language_strings[LANG_STRING_COUNT] = { _("KICK #channel nick [reason]"), /* CHAN_BAN_SYNTAX */ _("BAN #channel nick [reason]"), + /* CHAN_MODE_SYNTAX */ + _("MODE \037channel\037 {LOCK|SET} [\037modes\037 | {ADD|DEL|LIST} [\037what\037]]"), + /* CHAN_MODE_LOCK_UNKNOWN */ + _("Unknown mode character %c ignored."), + /* CHAN_MODE_LOCK_MISSING_PARAM */ + _("Missing parameter for mode %c."), + /* CHAN_MODE_LOCK_NONE */ + _("Channel %s has no mode locks."), + /* CHAN_MODE_LOCK_HEADER */ + _("Mode locks for %s:"), + /* CHAN_MODE_LOCKED */ + _("%c%c%s locked on %s"), + /* CHAN_MODE_NOT_LOCKED */ + _("%c is not locked on %s."), + /* CHAN_MODE_UNLOCKED */ + _("%c%c%s has been unlocked from %s."), + /* CHAN_MODE_LIST_FMT */ + _("%c%c%s, by %s on %s"), /* MEMO_HAVE_NEW_MEMO */ _("You have 1 new memo."), /* MEMO_HAVE_NEW_MEMOS */ @@ -3338,6 +3360,8 @@ const char *const language_strings[LANG_STRING_COUNT] = { _(" DEOP Deops a selected nick on a channel"), /* CHAN_HELP_CMD_CLONE */ _(" CLONE Copy all settings from one channel to another"), + /* CHAN_HELP_CMD_MODE */ + _(" MODE Control modes and mode locks on a channel"), /* CHAN_HELP */ _("%S allows you to register and control various\n" "aspects of channels. %S can often prevent\n" @@ -4062,6 +4086,26 @@ const char *const language_strings[LANG_STRING_COUNT] = { "target channel. If access, akick, or badwords is specified then only\n" "the respective settings are transferred. You must have founder level\n" "access to \037channel\037 and \037target\037."), + /* CHAN_HELP_MODE */ + _("Syntax: \002MODE \037channel\037 LOCK {ADD|DEL|LIST} [\037what\037]\002\n" + " \002MODE \037channel\037 SET \037modes\037\002\n" + " \n" + "Mainly controls mode locks and mode access (which is different from channel access)\n" + "on a channel.\n" + " \n" + "The \002MODE LOCK\002 command allows you to add, delete, and view mode locks on a channel.\n" + "If a mode is locked on or off, services will not allow that mode to be changed.\n" + "Example:\n" + " \002MODE #channel LOCK ADD +bmnt *!*@*aol*\002\n" + " \n" + "The \002MODE SET\002 command allows you to set modes through services. Wildcards * and ? may\n" + "be given as parameters for list and status modes.\n" + "Example:\n" + " \002MODE #channel SET +v *\002\n" + " Sets voice status to all users in the channel.\n" + " \n" + " \002MODE #channel SET -b ~c:*\n" + " Clears all extended bans that start with ~c:"), /* CHAN_SERVADMIN_HELP */ _(" \n" "Services Operators can also drop any channel without needing\n" diff --git a/src/misc.cpp b/src/misc.cpp index 7e02cc072..c885188f8 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -831,6 +831,74 @@ char *str_signed(unsigned char *str) return nstr; } +bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case_sensitive) +{ + size_t s = 0, m = 0, str_len = str.length(), mask_len = mask.length(); + + while (s < str_len && m < mask_len && mask[m] != '*') + { + char string = str[s], wild = mask[m]; + if (case_sensitive) + { + if (wild != string && wild != '?') + return false; + } + else + { + if (tolower(wild) != tolower(string) && wild != '?') + return false; + } + + ++m; + ++s; + } + + size_t sp = Anope::string::npos, mp = Anope::string::npos; + while (s < str_len) + { + char string = str[s], wild = mask[m]; + if (wild == '*') + { + if (++m == mask_len) + return 1; + + mp = m; + sp = s + 1; + } + else if (case_sensitive) + { + if (wild == string || wild == '?') + { + ++m; + ++s; + } + else + { + m = mp; + s = sp++; + } + } + else + { + if (tolower(wild) == tolower(string) || wild == '?') + { + ++m; + ++s; + } + else + { + m = mp; + s = sp++; + } + } + } + + if (mask[m] == '*') + ++m; + + return m == mask_len; +} + /* * strlcat and strlcpy were ripped from openssh 2.5.1p2 * They had the following Copyright info: @@ -1107,11 +1175,7 @@ uint16 netmask_to_cidr(uint32 mask) */ bool str_is_wildcard(const Anope::string &str) { - for (Anope::string::const_iterator c = str.begin(), c_end = str.end(); c != c_end; ++c) - if (*c == '*' || *c == '?') - return true; - - return false; + return str.find_first_of("*?") != Anope::string::npos; } /** @@ -1121,11 +1185,7 @@ bool str_is_wildcard(const Anope::string &str) */ bool str_is_pure_wildcard(const Anope::string &str) { - for (Anope::string::const_iterator c = str.begin(), c_end = str.end(); c != c_end; ++c) - if (*c != '*') - return false; - - return true; + return str.find_first_not_of('*') == Anope::string::npos; } /*************************************************************************/ diff --git a/src/modes.cpp b/src/modes.cpp index 6c6d43ad9..4d31f2232 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -27,53 +27,42 @@ std::map<ChannelModeName, ChannelMode *> ModeManager::ChannelModesByName; /* Number of generic modes we support */ unsigned GenericChannelModes = 0, GenericUserModes = 0; -/* Default mlocked modes on */ -Flags<ChannelModeName, CMODE_END * 2> DefMLockOn; -/* Default mlocked modes off */ -Flags<ChannelModeName, CMODE_END * 2> DefMLockOff; -/* Map for default mlocked mode parameters */ -std::map<ChannelModeName, Anope::string> DefMLockParams; +/* Default mlocked modes */ +std::multimap<ChannelModeName, ModeLock> def_mode_locks; /** Parse the mode string from the config file and set the default mlocked modes */ void SetDefaultMLock(ServerConfig *config) { - DefMLockOn.ClearFlags(); - DefMLockOff.ClearFlags(); - DefMLockParams.clear(); - Flags<ChannelModeName, CMODE_END * 2> *ptr = NULL; + def_mode_locks.clear(); - Anope::string modes, param; + Anope::string modes; spacesepstream sep(config->MLock); sep.GetToken(modes); + int adding = -1; for (unsigned i = 0, end_mode = modes.length(); i < end_mode; ++i) { if (modes[i] == '+') - ptr = &DefMLockOn; + adding = 1; else if (modes[i] == '-') - ptr = &DefMLockOff; - else + adding = 0; + else if (adding != -1) { - if (!ptr) - continue; - ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]); - if (cm && (cm->Type == MODE_REGULAR || cm->Type == MODE_PARAM)) + if (cm && cm->Type != MODE_STATUS) { - ptr->SetFlag(cm->Name); - - if (ptr == &DefMLockOn && cm->Type == MODE_PARAM) + Anope::string param; + if (adding == 1 && cm->Type != MODE_REGULAR && !sep.GetToken(param)) // MODE_LIST OR MODE_PARAM { - if (sep.GetToken(param)) - DefMLockParams.insert(std::make_pair(cm->Name, param)); - else - { - Log() << "Warning: Got default mlock mode " << cm->ModeChar << " with no param?"; - ptr->UnsetFlag(cm->Name); - } + Log() << "Warning: Got default mlock mode " << cm->ModeChar << " with no param?"; + continue; } + + if (cm->Type != MODE_LIST) // Only MODE_LIST can have duplicates + def_mode_locks.erase(cm->Name); + def_mode_locks.insert(std::make_pair(cm->Name, ModeLock(adding == 1, cm->Name, param))); } } } @@ -298,36 +287,20 @@ bool ChannelModeRegistered::CanSet(User *u) const * @param chan The channel * @param mask The ban */ -void ChannelModeBan::AddMask(Channel *chan, const Anope::string &mask) +void ChannelModeBan::OnAdd(Channel *chan, const Anope::string &mask) { /* check for NULL values otherwise we will segfault */ if (!chan || mask.empty()) - { - Log() << "add_ban called with NULL values"; return; - } - - /* Check if the list already exists, if not create it. - * Create a new ban and add it to the list.. ~ Viper */ - if (!chan->bans) - chan->bans = list_create(); - Entry *ban = entry_add(chan->bans, mask); - if (!ban) - throw CoreException("Creating new ban entry failed"); - - /* Check whether it matches a botserv bot after adding internally - * and parsing it through cidr support. ~ Viper */ + /* Check whether it matches a botserv bot */ if (!Config->s_BotServ.empty() && Config->BSSmartJoin && chan->ci && chan->ci->bi && chan->FindUser(chan->ci->bi)) { BotInfo *bi = chan->ci->bi; - if (entry_match(ban, bi->nick, bi->GetIdent(), bi->host, 0)) - { - ircdproto->SendMode(bi, chan, "-b %s", mask.c_str()); - entry_delete(chan->bans, ban); - return; - } + Entry ban(mask); + if (ban.Matches(bi)) + chan->RemoveMode(NULL, CMODE_BAN, mask); } Log(LOG_DEBUG) << "Added ban " << mask << " to channel " << chan->name; @@ -337,41 +310,22 @@ void ChannelModeBan::AddMask(Channel *chan, const Anope::string &mask) * @param chan The channel * @param mask The ban */ -void ChannelModeBan::DelMask(Channel *chan, const Anope::string &mask) +void ChannelModeBan::OnDel(Channel *chan, const Anope::string &mask) { - /* Sanity check as it seems some IRCD will just send -b without a mask */ - if (mask.empty() || !chan->bans || !chan->bans->count) + if (!chan || mask.empty()) return; - Entry *ban = elist_find_mask(chan->bans, mask); - if (ban) - { - entry_delete(chan->bans, ban); - - Log(LOG_DEBUG) << "Deleted ban " << mask << " from channel " << chan->name; - } + Log(LOG_DEBUG) << "Deleted ban " << mask << " from channel " << chan->name; } /** Add an except to the channel * @param chan The channel * @param mask The except */ -void ChannelModeExcept::AddMask(Channel *chan, const Anope::string &mask) +void ChannelModeExcept::OnAdd(Channel *chan, const Anope::string &mask) { if (!chan || mask.empty()) - { - Log() << "add_exception called with NULL values"; return; - } - - /* Check if the list already exists, if not create it. - * Create a new exception and add it to the list.. ~ Viper */ - if (!chan->excepts) - chan->excepts = list_create(); - - Entry *exception = entry_add(chan->excepts, mask); - if (!exception) - throw CoreException("Creating new exception entry failed"); Log(LOG_DEBUG) << "Added except " << mask << " to channel " << chan->name; } @@ -380,40 +334,22 @@ void ChannelModeExcept::AddMask(Channel *chan, const Anope::string &mask) * @param chan The channel * @param mask The except */ -void ChannelModeExcept::DelMask(Channel *chan, const Anope::string &mask) +void ChannelModeExcept::OnDel(Channel *chan, const Anope::string &mask) { - /* Sanity check as it seems some IRCD will just send -e without a mask */ - if (mask.empty() || !chan->excepts || !chan->excepts->count) + if (!chan || mask.empty()) return; - Entry *exception = elist_find_mask(chan->excepts, mask); - if (exception) - { - entry_delete(chan->excepts, exception); - Log(LOG_DEBUG) << "Deleted except " << mask << " to channel " << chan->name; - } + Log(LOG_DEBUG) << "Deleted except " << mask << " to channel " << chan->name; } /** Add an invex to the channel * @param chan The channel * @param mask The invex */ -void ChannelModeInvex::AddMask(Channel *chan, const Anope::string &mask) +void ChannelModeInvex::OnAdd(Channel *chan, const Anope::string &mask) { if (!chan || mask.empty()) - { - Log() << "add_invite called with NULL values"; return; - } - - /* Check if the list already exists, if not create it. - * Create a new invite and add it to the list.. ~ Viper */ - if (!chan->invites) - chan->invites = list_create(); - - Entry *invite = entry_add(chan->invites, mask); - if (!invite) - throw CoreException("Creating new invex entry failed"); Log(LOG_DEBUG) << "Added invite " << mask << " to channel " << chan->name; @@ -423,18 +359,12 @@ void ChannelModeInvex::AddMask(Channel *chan, const Anope::string &mask) * @param chan The channel * @param mask The index */ -void ChannelModeInvex::DelMask(Channel *chan, const Anope::string &mask) +void ChannelModeInvex::OnDel(Channel *chan, const Anope::string &mask) { - /* Sanity check as it seems some IRCD will just send -I without a mask */ - if (mask.empty() || !chan->invites || !chan->invites->count) + if (!chan || mask.empty()) return; - Entry *invite = elist_find_mask(chan->invites, mask); - if (invite) - { - entry_delete(chan->invites, invite); - Log(LOG_DEBUG) << "Deleted invite " << mask << " to channel " << chan->name; - } + Log(LOG_DEBUG) << "Deleted invite " << mask << " to channel " << chan->name; } void StackerInfo::AddMode(Mode *mode, bool Set, const Anope::string &Param) diff --git a/src/operserv.cpp b/src/operserv.cpp index 5f6f8c2be..727432585 100644 --- a/src/operserv.cpp +++ b/src/operserv.cpp @@ -428,7 +428,18 @@ XLine *XLineManager::Check(User *u) if (!x->GetUser().empty() && !Anope::Match(u->GetIdent(), x->GetUser())) continue; - if (x->GetHost().empty() || (u->ip() && Anope::Match(u->ip.addr(), x->GetHost())) || Anope::Match(u->host, x->GetHost()) || (!u->chost.empty() && Anope::Match(u->chost, x->GetHost())) || (!u->vhost.empty() && Anope::Match(u->vhost, x->GetHost()))) + if (u->ip() && !x->GetHost().empty()) + { + try + { + cidr cidr_ip(x->GetHost()); + if (cidr_ip.match(u->ip)) + return x; + } + catch (const SocketException &) { } + } + + if (x->GetHost().empty() || (Anope::Match(u->host, x->GetHost()) || (!u->chost.empty() && Anope::Match(u->chost, x->GetHost())) || (!u->vhost.empty() && Anope::Match(u->vhost, x->GetHost())))) { OnMatch(u, x); return x; diff --git a/src/regchannel.cpp b/src/regchannel.cpp index b4c42cb82..8228e4ffb 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -33,9 +33,7 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) this->name = chname; - this->mlock_on = DefMLockOn; - this->mlock_off = DefMLockOff; - this->Params = DefMLockParams; + this->mode_locks = def_mode_locks; size_t t; /* Set default channel flags */ @@ -392,7 +390,9 @@ void ChannelInfo::LoadMLock() std::vector<Anope::string> modenames_on, modenames_off; // Force +r - this->SetMLock(CMODE_REGISTERED, true); + ChannelMode *chm = ModeManager::FindChannelModeByName(CMODE_REGISTERED); + if (chm) + this->SetMLock(chm, true); this->GetExtRegular("db_mlock_modes_on", modenames_on); this->GetExtRegular("db_mlock_modes_off", modenames_off); @@ -405,7 +405,7 @@ void ChannelInfo::LoadMLock() if (m && m->NameAsString.equals_cs(*it)) { ChannelMode *cm = debug_cast<ChannelMode *>(m); - this->SetMLock(cm->Name, true); + this->SetMLock(cm, true); } } for (std::vector<Anope::string>::iterator it = modenames_off.begin(), it_end = modenames_off.end(); it != it_end; ++it) @@ -415,7 +415,7 @@ void ChannelInfo::LoadMLock() if (m && m->NameAsString.equals_cs(*it)) { ChannelMode *cm = debug_cast<ChannelMode *>(m); - this->SetMLock(cm->Name, false); + this->SetMLock(cm, false); } } } @@ -429,15 +429,28 @@ void ChannelInfo::LoadMLock() if (m && m->Class == MC_CHANNEL) { ChannelMode *cm = debug_cast<ChannelMode *>(m); - this->SetMLock(cm->Name, true, it->second); + this->SetMLock(cm, true, it->second); } } } + if (this->GetExtRegular("db_mlp_off", params)) + { + for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = params.begin(), it_end = params.end(); it != it_end; ++it) + { + Mode *m = ModeManager::FindModeByName(it->first); + if (m && m->Class == MC_CHANNEL) + { + ChannelMode *cm = debug_cast<ChannelMode *>(m); + this->SetMLock(cm, false, it->second); + } + } + } this->Shrink("db_mlock_modes_on"); this->Shrink("db_mlock_modes_off"); this->Shrink("db_mlp"); + this->Shrink("db_mlp_off"); /* Create perm channel */ if (this->HasFlag(CI_PERSIST) && !this->c) @@ -453,132 +466,135 @@ void ChannelInfo::LoadMLock() } /** Check if a mode is mlocked - * @param Name The mode + * @param mode The mode * @param status True to check mlock on, false for mlock off * @return true on success, false on fail */ -bool ChannelInfo::HasMLock(ChannelModeName Name, bool status) const +bool ChannelInfo::HasMLock(ChannelMode *mode, const Anope::string ¶m, bool status) const { - if (status) - return this->mlock_on.HasFlag(Name); - else - return this->mlock_off.HasFlag(Name); + std::map<ChannelModeName, ModeLock>::const_iterator it = this->mode_locks.find(mode->Name); + + if (it != this->mode_locks.end()) + { + if (mode->Type != MODE_REGULAR) + { + std::map<ChannelModeName, ModeLock>::const_iterator it_end = this->mode_locks.upper_bound(mode->Name); + for (; it != it_end; ++it) + { + const ModeLock &ml = it->second; + if (ml.param == param) + return true; + } + } + else + return it->second.set == status; + } + return false; } /** Set a mlock - * @param Name The mode + * @param mode The mode * @param status True for mlock on, false for mlock off * @param param The param to use for this mode, if required * @return true on success, false on failure (module blocking) */ -bool ChannelInfo::SetMLock(ChannelModeName Name, bool status, const Anope::string ¶m) +bool ChannelInfo::SetMLock(ChannelMode *mode, bool status, const Anope::string ¶m, const Anope::string &setter, time_t created) { - if (!status && !param.empty()) - throw CoreException("Was told to mlock a mode negatively with a param?"); + std::pair<ChannelModeName, ModeLock> ml = std::make_pair(mode->Name, ModeLock(status, mode->Name, param, setter, created)); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnMLock, OnMLock(this, Name, status, param)); + FOREACH_RESULT(I_OnMLock, OnMLock(this, &ml.second)); if (MOD_RESULT == EVENT_STOP) return false; - /* First, remove this everywhere */ - this->mlock_on.UnsetFlag(Name); - this->mlock_off.UnsetFlag(Name); - - std::map<ChannelModeName, Anope::string>::iterator it = Params.find(Name); - if (it != Params.end()) - Params.erase(it); - - if (status) - this->mlock_on.SetFlag(Name); - else - this->mlock_off.SetFlag(Name); - - if (status && !param.empty()) - this->Params.insert(std::make_pair(Name, param)); + /* First, remove this */ + this->RemoveMLock(mode, param); + + this->mode_locks.insert(ml); return true; } /** Remove a mlock - * @param Name The mode - * @return true on success, false on failure (module blocking) + * @param mode The mode + * @param param The param of the mode, required if it is a list or status mode + * @return true on success, false on failure */ -bool ChannelInfo::RemoveMLock(ChannelModeName Name) +bool ChannelInfo::RemoveMLock(ChannelMode *mode, const Anope::string ¶m) { EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, Name)); + FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, mode, param)); if (MOD_RESULT == EVENT_STOP) return false; - this->mlock_on.UnsetFlag(Name); - this->mlock_off.UnsetFlag(Name); - - std::map<ChannelModeName, Anope::string>::iterator it = Params.find(Name); - if (it != Params.end()) - this->Params.erase(it); + if (mode->Type == MODE_REGULAR || mode->Type == MODE_PARAM) + return this->mode_locks.erase(mode->Name) > 0; + else + { + // For list or status modes, we must check the parameter + std::multimap<ChannelModeName, ModeLock>::iterator it = this->mode_locks.find(mode->Name), it_end = this->mode_locks.upper_bound(mode->Name); + for (; it != it_end; ++it) + { + const ModeLock &ml = it->second; + if (ml.param == param) + { + this->mode_locks.erase(it); + return true; + } + } - return true; + return false; + } } /** Clear all mlocks on the channel */ void ChannelInfo::ClearMLock() { - this->mlock_on.ClearFlags(); - this->mlock_off.ClearFlags(); + this->mode_locks.clear(); } -/** Get the number of mlocked modes for this channel - * @param status true for mlock on, false for mlock off - * @return The number of mlocked modes +/** Get all of the mlocks for this channel + * @return The mlocks */ -size_t ChannelInfo::GetMLockCount(bool status) const +const std::multimap<ChannelModeName, ModeLock> &ChannelInfo::GetMLock() const { - if (status) - return this->mlock_on.FlagCount(); - else - return this->mlock_off.FlagCount(); + return this->mode_locks; } -/** Get a param from the channel - * @param Name The mode - * @param Target a string to put the param into - * @return true on success +/** Get a list of modes on a channel + * @param Name The mode name to get a list of + * @return a pair of iterators for the beginning and end of the list */ -bool ChannelInfo::GetParam(ChannelModeName Name, Anope::string &Target) const +std::pair<ChannelInfo::ModeList::iterator, ChannelInfo::ModeList::iterator> ChannelInfo::GetModeList(ChannelModeName Name) { - std::map<ChannelModeName, Anope::string>::const_iterator it = this->Params.find(Name); - - Target.clear(); - - if (it != this->Params.end()) - { - Target = it->second; - return true; - } - - return false; + return std::make_pair(this->mode_locks.find(Name), this->mode_locks.upper_bound(Name)); } -/** Check if a mode is set and has a param - * @param Name The mode +/** Get details for a specific mlock + * @param name The mode name + * @param param An optional param to match with + * @return The MLock, if any */ -bool ChannelInfo::HasParam(ChannelModeName Name) const +ModeLock *ChannelInfo::GetMLock(ChannelModeName name, const Anope::string ¶m) { - std::map<ChannelModeName, Anope::string>::const_iterator it = this->Params.find(Name); - - if (it != this->Params.end()) - return true; - - return false; -} + std::multimap<ChannelModeName, ModeLock>::iterator it = this->mode_locks.find(name); + if (it != this->mode_locks.end()) + { + if (param.empty()) + return &it->second; + else + { + std::multimap<ChannelModeName, ModeLock>::iterator it_end = this->mode_locks.upper_bound(name); + for (; it != it_end; ++it) + { + if (Anope::Match(param, it->second.param)) + return &it->second; + } + } + } -/** Clear all the params from the channel - */ -void ChannelInfo::ClearParams() -{ - Params.clear(); + return NULL; } /** Check whether a user is permitted to be on this channel diff --git a/src/sockets.cpp b/src/sockets.cpp index 9e32f85eb..0eb7733cf 100644 --- a/src/sockets.cpp +++ b/src/sockets.cpp @@ -171,6 +171,80 @@ void sockaddrs::ntop(int type, const void *src) throw CoreException("Invalid socket type"); } +cidr::cidr(const Anope::string &ip) +{ + if (ip.find_first_not_of("01234567890:./") != Anope::string::npos) + throw SocketException("Invalid IP"); + + bool ipv6 = ip.find(':') != Anope::string::npos; + size_t sl = ip.find_last_of('/'); + if (sl == Anope::string::npos) + { + this->cidr_ip = ip; + this->cidr_len = ipv6 ? 128 : 32; + this->addr.pton(ipv6 ? AF_INET6 : AF_INET, ip); + } + else + { + Anope::string real_ip = ip.substr(0, sl); + Anope::string cidr_range = ip.substr(sl + 1); + if (!cidr_range.is_pos_number_only()) + throw SocketException("Invalid CIDR range"); + + this->cidr_ip = real_ip; + this->cidr_len = convertTo<unsigned int>(cidr_range); + this->addr.pton(ipv6 ? AF_INET6 : AF_INET, real_ip); + } +} + +cidr::cidr(const Anope::string &ip, unsigned char len) +{ + bool ipv6 = ip.find(':') != Anope::string::npos; + this->addr.pton(ipv6 ? AF_INET6 : AF_INET, ip); + this->cidr_ip = ip; + this->cidr_len = len; +} + +Anope::string cidr::mask() const +{ + return this->cidr_ip + "/" + this->cidr_len; +} + +bool cidr::match(sockaddrs &other) +{ + if (this->addr.sa.sa_family != other.sa.sa_family) + return false; + + unsigned char *ip, *their_ip, byte; + + switch (this->addr.sa.sa_family) + { + case AF_INET: + ip = reinterpret_cast<unsigned char *>(&this->addr.sa4.sin_addr); + byte = this->cidr_len / 8; + their_ip = reinterpret_cast<unsigned char *>(&other.sa4.sin_addr); + break; + case AF_INET6: + ip = reinterpret_cast<unsigned char *>(&this->addr.sa6.sin6_addr); + byte = this->cidr_len / 8; + their_ip = reinterpret_cast<unsigned char *>(&other.sa6.sin6_addr); + break; + default: + throw SocketException("Invalid address type"); + } + + if (memcmp(ip, their_ip, byte)) + return false; + + ip += byte; + their_ip += byte; + byte = this->cidr_len % 8; + if ((*ip & byte) != (*their_ip & byte)) + return false; + + return true; +} + /** Default constructor */ SocketEngineBase::SocketEngineBase() diff --git a/src/users.cpp b/src/users.cpp index 27426819b..ac16c61ac 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -165,6 +165,11 @@ Anope::string User::GetMask() const return this->nick + "!" + this->ident + "@" + this->host; } +Anope::string User::GetDisplayedMask() const +{ + return this->nick + "!" + this->GetVIdent() + "@" + this->GetDisplayedHost(); +} + void User::SetRealname(const Anope::string &srealname) { if (srealname.empty()) @@ -921,7 +926,16 @@ bool is_excepted(ChannelInfo *ci, User *user) if (!ci->c || !ModeManager::FindChannelModeByName(CMODE_EXCEPT)) return false; - return elist_match_user(ci->c->excepts, user); + + std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> modes = ci->c->GetModeList(CMODE_EXCEPT); + for (; modes.first != modes.second; ++modes.first) + { + Entry e(modes.first->second); + if (e.Matches(user)) + return true; + } + + return false; } /*************************************************************************/ @@ -932,7 +946,14 @@ bool is_excepted_mask(ChannelInfo *ci, const Anope::string &mask) if (!ci->c || !ModeManager::FindChannelModeByName(CMODE_EXCEPT)) return false; - return elist_match_mask(ci->c->excepts, mask, 0); + std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> modes = ci->c->GetModeList(CMODE_EXCEPT); + for (; modes.first != modes.second; ++modes.first) + { + if (Anope::Match(modes.first->second, mask)) + return true; + } + + return false; } /*************************************************************************/ diff --git a/src/wildcard.cpp b/src/wildcard.cpp deleted file mode 100644 index c6883a4bc..000000000 --- a/src/wildcard.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "services.h" - -bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case_sensitive) -{ - size_t s = 0, m = 0, str_len = str.length(), mask_len = mask.length(); - - while (s < str_len && m < mask_len && mask[m] != '*') - { - char string = str[s], wild = mask[m]; - if (case_sensitive) - { - if (wild != string && wild != '?') - return false; - } - else - { - if (tolower(wild) != tolower(string) && wild != '?') - return false; - } - - ++m; - ++s; - } - - size_t sp = 0, mp = 0; - while (s < str_len) - { - char string = str[s], wild = mask[m]; - if (wild == '*') - { - if (++m == mask_len) - return 1; - - mp = m; - sp = s + 1; - } - else - { - if (case_sensitive) - { - if (wild == string || wild == '?') - { - ++m; - ++s; - } - else - { - m = mp; - s = sp++; - } - } - else - { - if (tolower(wild) == tolower(string) || wild == '?') - { - ++m; - ++s; - } - else - { - m = mp; - s = sp++; - } - } - } - } - - if (mask[m] == '*') - ++m; - - return m == mask_len; -} |