modes.cpp

Go to the documentation of this file.
00001 /* Mode support
00002  *
00003  * Copyright (C) 2008-2011 Adam <Adam@anope.org>
00004  * Copyright (C) 2008-2013 Anope Team <team@anope.org>
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  */
00009 
00010 #include "services.h"
00011 #include "modules.h"
00012 #include "config.h"
00013 #include "sockets.h"
00014 #include "protocol.h"
00015 #include "channels.h"
00016 
00017 /* List of pairs of user/channels and their stacker info */
00018 std::map<User *, StackerInfo *> ModeManager::UserStackerObjects;
00019 std::map<Channel *, StackerInfo *> ModeManager::ChannelStackerObjects;
00020 
00021 /* List of all modes Anope knows about */
00022 std::vector<ChannelMode *> ModeManager::ChannelModes;
00023 std::vector<UserMode *> ModeManager::UserModes;
00024 
00025 /* Number of generic modes we support */
00026 unsigned ModeManager::GenericChannelModes = 0, ModeManager::GenericUserModes = 0;
00027 
00028 /* Default channel mode lock */
00029 std::list<std::pair<Anope::string, Anope::string> > ModeManager::ModeLockOn;
00030 std::list<Anope::string> ModeManager::ModeLockOff;
00031 
00032 /* Default modes bots have on channels */
00033 ChannelStatus ModeManager::DefaultBotModes;
00034 
00035 Anope::string ChannelStatus::BuildCharPrefixList() const
00036 {
00037         Anope::string ret;
00038 
00039         for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00040         {
00041                 ChannelMode *cm = ModeManager::ChannelModes[i];
00042 
00043                 if (this->modes.count(cm->name))
00044                         ret += cm->mchar;
00045         }
00046 
00047         return ret;
00048 }
00049 
00050 Anope::string ChannelStatus::BuildModePrefixList() const
00051 {
00052         Anope::string ret;
00053 
00054         for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00055         {
00056                 ChannelMode *cm = ModeManager::ChannelModes[i];
00057 
00058                 if (this->modes.count(cm->name))
00059                 {
00060                         ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
00061                         ret += cms->Symbol;
00062                 }
00063         }
00064 
00065         return ret;
00066 }
00067 
00068 Mode::Mode(const Anope::string &mname, ModeClass mcl, char mch, ModeType mt) : name(mname), mclass(mcl), mchar(mch), type(mt)
00069 {
00070 }
00071 
00072 Mode::~Mode()
00073 {
00074 }
00075 
00076 UserMode::UserMode(const Anope::string &un, char mch) : Mode(un, MC_USER, mch, MODE_REGULAR)
00077 {
00078 }
00079 
00080 UserMode::~UserMode()
00081 {
00082 }
00083 
00084 UserModeParam::UserModeParam(const Anope::string &un, char mch) : UserMode(un, mch)
00085 {
00086         this->type = MODE_PARAM;
00087 }
00088 
00089 ChannelMode::ChannelMode(const Anope::string &cm, char mch) : Mode(cm, MC_CHANNEL, mch, MODE_REGULAR)
00090 {
00091 }
00092 
00093 ChannelMode::~ChannelMode()
00094 {
00095 }
00096 
00097 bool ChannelMode::CanSet(User *u) const
00098 {
00099         if (Config->NoMLock.find(this->mchar) != Anope::string::npos || Config->CSRequire.find(this->mchar) != Anope::string::npos)
00100                 return false;
00101         return true;
00102 }
00103 
00104 ChannelModeList::ChannelModeList(const Anope::string &cm, char mch) : ChannelMode(cm, mch)
00105 {
00106         this->type = MODE_LIST;
00107 }
00108 
00109 ChannelModeList::~ChannelModeList()
00110 {
00111 }
00112 
00113 ChannelModeParam::ChannelModeParam(const Anope::string &cm, char mch, bool ma) : ChannelMode(cm, mch), minus_no_arg(ma)
00114 {
00115         this->type = MODE_PARAM;
00116 }
00117 
00118 ChannelModeParam::~ChannelModeParam()
00119 {
00120 }
00121 
00122 ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar, char mSymbol, short mlevel) : ChannelMode(mname, modeChar), Symbol(mSymbol), level(mlevel)
00123 {
00124         this->type = MODE_STATUS;
00125 }
00126 
00127 ChannelModeStatus::~ChannelModeStatus()
00128 {
00129 }
00130 
00131 bool ChannelModeKey::IsValid(const Anope::string &value) const
00132 {
00133         if (!value.empty() && value.find(':') == Anope::string::npos && value.find(',') == Anope::string::npos)
00134                 return true;
00135 
00136         return false;
00137 }
00138 
00139 bool ChannelModeAdmin::CanSet(User *u) const
00140 {
00141         if (u && u->HasMode("OPER"))
00142                 return true;
00143 
00144         return false;
00145 }
00146 
00147 bool ChannelModeOper::CanSet(User *u) const
00148 {
00149         if (u && u->HasMode("OPER"))
00150                 return true;
00151 
00152         return false;
00153 }
00154 
00155 bool ChannelModeRegistered::CanSet(User *u) const
00156 {
00157         return false;
00158 }
00159 
00160 void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string &param)
00161 {
00162         bool is_param = mode->type == MODE_PARAM;
00163 
00164         std::list<std::pair<Mode *, Anope::string> > *list, *otherlist;
00165         if (set)
00166         {
00167                 list = &AddModes;
00168                 otherlist = &DelModes;
00169         }
00170         else
00171         {
00172                 list = &DelModes;
00173                 otherlist = &AddModes;
00174         }
00175 
00176         /* Loop through the list and find if this mode is already on here */
00177         std::list<std::pair<Mode *, Anope::string > >::iterator it, it_end;
00178         for (it = list->begin(), it_end = list->end(); it != it_end; ++it)
00179         {
00180                 /* The param must match too (can have multiple status or list modes), but
00181                  * if it is a param mode it can match no matter what the param is
00182                  */
00183                 if (it->first == mode && (is_param || param.equals_cs(it->second)))
00184                 {
00185                         list->erase(it);
00186                         /* It can only be on this list once */
00187                         break;
00188                 }
00189         }
00190         /* If the mode is on the other list, remove it from there (eg, we dont want +o-o Adam Adam) */
00191         for (it = otherlist->begin(), it_end = otherlist->end(); it != it_end; ++it)
00192         {
00193                 /* The param must match too (can have multiple status or list modes), but
00194                  * if it is a param mode it can match no matter what the param is
00195                  */
00196                 if (it->first == mode && (is_param || param.equals_cs(it->second)))
00197                 {
00198                         otherlist->erase(it);
00199                         return;
00200                         /* Note that we return here because this is like setting + and - on the same mode within the same
00201                          * cycle, no change is made. This causes no problems with something like - + and -, because after the
00202                          * second mode change the list is empty, and the third mode change starts fresh.
00203                          */
00204                 }
00205         }
00206 
00207         /* Add this mode and its param to our list */
00208         list->push_back(std::make_pair(mode, param));
00209 }
00210 
00211 static class ModePipe : public Pipe
00212 {
00213  public:
00214         void OnNotify()
00215         {
00216                 ModeManager::ProcessModes();
00217         }
00218 } *modePipe;
00219 
00224 template<typename List, typename Object>
00225 static StackerInfo *GetInfo(List &l, Object *o)
00226 {
00227         typename List::const_iterator it = l.find(o);
00228         if (it != l.end())
00229                 return it->second;
00230 
00231         StackerInfo *s = new StackerInfo();
00232         l[o] = s;
00233         return s;
00234 }
00235 
00236 std::list<Anope::string> ModeManager::BuildModeStrings(StackerInfo *info)
00237 {
00238         std::list<Anope::string> ret;
00239         std::list<std::pair<Mode *, Anope::string> >::iterator it, it_end;
00240         Anope::string buf = "+", parambuf;
00241         unsigned NModes = 0;
00242 
00243         for (it = info->AddModes.begin(), it_end = info->AddModes.end(); it != it_end; ++it)
00244         {
00245                 if (++NModes > IRCD->MaxModes)
00246                 {
00247                         ret.push_back(buf + parambuf);
00248                         buf = "+";
00249                         parambuf.clear();
00250                         NModes = 1;
00251                 }
00252 
00253                 buf += it->first->mchar;
00254 
00255                 if (!it->second.empty())
00256                         parambuf += " " + it->second;
00257         }
00258 
00259         if (buf[buf.length() - 1] == '+')
00260                 buf.erase(buf.length() - 1);
00261 
00262         buf += "-";
00263         for (it = info->DelModes.begin(), it_end = info->DelModes.end(); it != it_end; ++it)
00264         {
00265                 if (++NModes > IRCD->MaxModes)
00266                 {
00267                         ret.push_back(buf + parambuf);
00268                         buf = "-";
00269                         parambuf.clear();
00270                         NModes = 1;
00271                 }
00272 
00273                 buf += it->first->mchar;
00274 
00275                 if (!it->second.empty())
00276                         parambuf += " " + it->second;
00277         }
00278 
00279         if (buf[buf.length() - 1] == '-')
00280                 buf.erase(buf.length() - 1);
00281 
00282         if (!buf.empty())
00283                 ret.push_back(buf + parambuf);
00284 
00285         return ret;
00286 }
00287 
00288 bool ModeManager::AddUserMode(UserMode *um)
00289 {
00290         if (ModeManager::FindUserModeByChar(um->mchar) != NULL)
00291                 return false;
00292         
00293         if (um->name.empty())
00294         {
00295                 um->name = stringify(++GenericUserModes);
00296                 Log() << "ModeManager: Added generic support for user mode " << um->mchar;
00297         }
00298 
00299         ModeManager::UserModes.push_back(um);
00300 
00301         FOREACH_MOD(I_OnUserModeAdd, OnUserModeAdd(um));
00302 
00303         return true;
00304 }
00305 
00306 bool ModeManager::AddChannelMode(ChannelMode *cm)
00307 {
00308         if (ModeManager::FindChannelModeByChar(cm->mchar) != NULL)
00309                 return false;
00310 
00311         if (cm->name.empty())
00312         {
00313                 cm->name = stringify(++GenericChannelModes);
00314                 Log() << "ModeManager: Added generic support for channel mode " << cm->mchar;
00315         }
00316 
00317         ModeManager::ChannelModes.push_back(cm);
00318 
00319         /* Apply this mode to the new default mlock if its used */
00320         UpdateDefaultMLock(Config);
00321 
00322         FOREACH_MOD(I_OnChannelModeAdd, OnChannelModeAdd(cm));
00323 
00324         return true;
00325 }
00326 
00327 void ModeManager::RemoveUserMode(UserMode *um)
00328 {
00329         for (unsigned i = 0; i < ModeManager::UserModes.size(); ++i)
00330         {
00331                 UserMode *mode = ModeManager::UserModes[i];
00332                 if (um == mode)
00333                 {
00334                         ModeManager::UserModes.erase(ModeManager::UserModes.begin() + i);
00335                         break;
00336                 }
00337         }
00338 
00339         StackerDel(um);
00340 }
00341 
00342 void ModeManager::RemoveChannelMode(ChannelMode *cm)
00343 {
00344         for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00345         {
00346                 ChannelMode *mode = ModeManager::ChannelModes[i];
00347                 if (cm == mode)
00348                 {
00349                         ModeManager::ChannelModes.erase(ModeManager::ChannelModes.begin() + i);
00350                         break;
00351                 }
00352         }
00353 
00354         StackerDel(cm);
00355 }
00356 
00357 ChannelMode *ModeManager::FindChannelModeByChar(char Mode)
00358 {
00359         for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00360         {
00361                 ChannelMode *cm = ModeManager::ChannelModes[i];
00362                 if (cm->mchar == Mode)
00363                         return cm;
00364         }
00365 
00366         return NULL;
00367 }
00368 
00369 UserMode *ModeManager::FindUserModeByChar(char Mode)
00370 {
00371         for (unsigned i = 0; i < ModeManager::UserModes.size(); ++i)
00372         {
00373                 UserMode *um = ModeManager::UserModes[i];
00374                 if (um->mchar == Mode)
00375                         return um;
00376         }
00377 
00378         return NULL;
00379 }
00380 
00381 ChannelMode *ModeManager::FindChannelModeByName(const Anope::string &name)
00382 {
00383         for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00384         {
00385                 ChannelMode *cm = ModeManager::ChannelModes[i];
00386                 if (cm->name == name)
00387                         return cm;
00388         }
00389 
00390         return NULL;
00391 }
00392 
00393 UserMode *ModeManager::FindUserModeByName(const Anope::string &name)
00394 {
00395         for (unsigned i = 0; i < ModeManager::UserModes.size(); ++i)
00396         {
00397                 UserMode *um = ModeManager::UserModes[i];
00398                 if (um->name == name)
00399                         return um;
00400         }
00401 
00402         return NULL;
00403 }
00404 
00405 char ModeManager::GetStatusChar(char Value)
00406 {
00407         for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00408         {
00409                 ChannelMode *cm = ModeManager::ChannelModes[i];
00410                 if (cm->type == MODE_STATUS)
00411                 {
00412                         ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
00413 
00414                         if (Value == cms->Symbol)
00415                                 return cms->mchar;
00416                 }
00417         }
00418 
00419         return 0;
00420 }
00421 
00422 void ModeManager::StackerAdd(const BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const Anope::string &Param)
00423 {
00424         StackerInfo *s = GetInfo(ChannelStackerObjects, c);
00425         s->AddMode(cm, Set, Param);
00426         if (bi)
00427                 s->bi = bi;
00428         else
00429                 s->bi = c->ci->WhoSends();
00430 
00431         if (!modePipe)
00432                 modePipe = new ModePipe();
00433         modePipe->Notify();
00434 }
00435 
00436 void ModeManager::StackerAdd(const BotInfo *bi, User *u, UserMode *um, bool Set, const Anope::string &Param)
00437 {
00438         StackerInfo *s = GetInfo(UserStackerObjects, u);
00439         s->AddMode(um, Set, Param);
00440         if (bi)
00441                 s->bi = bi;
00442         else
00443                 s->bi = NULL;
00444 
00445         if (!modePipe)
00446                 modePipe = new ModePipe();
00447         modePipe->Notify();
00448 }
00449 
00450 void ModeManager::ProcessModes()
00451 {
00452         if (!UserStackerObjects.empty())
00453         {
00454                 for (std::map<User *, StackerInfo *>::const_iterator it = UserStackerObjects.begin(), it_end = UserStackerObjects.end(); it != it_end; ++it)
00455                 {
00456                         User *u = it->first;
00457                         StackerInfo *s = it->second;
00458 
00459                         std::list<Anope::string> ModeStrings = BuildModeStrings(s);
00460                         for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit)
00461                                 IRCD->SendMode(s->bi, u, lit->c_str());
00462                         delete it->second;
00463                 }
00464                 UserStackerObjects.clear();
00465         }
00466 
00467         if (!ChannelStackerObjects.empty())
00468         {
00469                 for (std::map<Channel *, StackerInfo *>::const_iterator it = ChannelStackerObjects.begin(), it_end = ChannelStackerObjects.end(); it != it_end; ++it)
00470                 {
00471                         Channel *c = it->first;
00472                         StackerInfo *s = it->second;
00473 
00474                         std::list<Anope::string> ModeStrings = BuildModeStrings(s);
00475                         for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit)
00476                                 IRCD->SendMode(s->bi, c, lit->c_str());
00477                         delete it->second;
00478                 }
00479                 ChannelStackerObjects.clear();
00480         }
00481 }
00482 
00483 void ModeManager::StackerDel(User *u)
00484 {
00485         UserStackerObjects.erase(u);
00486 }
00487 
00488 void ModeManager::StackerDel(Channel *c)
00489 {
00490         ChannelStackerObjects.erase(c);
00491 }
00492 
00493 void ModeManager::StackerDel(Mode *m)
00494 {
00495         for (std::map<User *, StackerInfo *>::const_iterator it = UserStackerObjects.begin(), it_end = UserStackerObjects.end(); it != it_end;)
00496         {
00497                 StackerInfo *si = it->second;
00498                 ++it;
00499 
00500                 for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->AddModes.begin(), it2_end = si->AddModes.end(); it2 != it2_end;)
00501                 {
00502                         if (it2->first == m)
00503                                 it2 = si->AddModes.erase(it2);
00504                         else
00505                                 ++it2;
00506                 }
00507 
00508                 for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->DelModes.begin(), it2_end = si->DelModes.end(); it2 != it2_end;)
00509                 {
00510                         if (it2->first == m)
00511                                 it2 = si->DelModes.erase(it2);
00512                         else
00513                                 ++it2;
00514                 }
00515         }
00516 
00517         for (std::map<Channel *, StackerInfo *>::const_iterator it = ChannelStackerObjects.begin(), it_end = ChannelStackerObjects.end(); it != it_end;)
00518         {
00519                 StackerInfo *si = it->second;
00520                 ++it;
00521 
00522                 for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->AddModes.begin(), it2_end = si->AddModes.end(); it2 != it2_end;)
00523                 {
00524                         if (it2->first == m)
00525                                 it2 = si->AddModes.erase(it2);
00526                         else
00527                                 ++it2;
00528                 }
00529 
00530                 for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->DelModes.begin(), it2_end = si->DelModes.end(); it2 != it2_end;)
00531                 {
00532                         if (it2->first == m)
00533                                 it2 = si->DelModes.erase(it2);
00534                         else
00535                                 ++it2;
00536                 }
00537         }
00538 }
00539 
00540 void ModeManager::UpdateDefaultMLock(ServerConfig *config)
00541 {
00542         ModeLockOn.clear();
00543         ModeLockOff.clear();
00544 
00545         Anope::string modes;
00546         spacesepstream sep(config->MLock);
00547         sep.GetToken(modes);
00548 
00549         int adding = -1;
00550         for (unsigned i = 0, end_mode = modes.length(); i < end_mode; ++i)
00551         {
00552                 if (modes[i] == '+')
00553                         adding = 1;
00554                 else if (modes[i] == '-')
00555                         adding = 0;
00556                 else if (adding != -1)
00557                 {
00558                         ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
00559 
00560                         if (cm && cm->type != MODE_STATUS)
00561                         {
00562                                 Anope::string param;
00563                                 if (adding == 1 && cm->type != MODE_REGULAR && !sep.GetToken(param)) // MODE_LIST OR MODE_PARAM
00564                                 {
00565                                         Log() << "Warning: Got default mlock mode " << cm->mchar << " with no param?";
00566                                         continue;
00567                                 }
00568 
00569                                 if (cm->type != MODE_LIST) // Only MODE_LIST can have duplicates
00570                                 {
00571                                         for (std::list<std::pair<Anope::string, Anope::string> >::iterator it = ModeLockOn.begin(), it_end = ModeLockOn.end(); it != it_end; ++it)
00572                                                 if (it->first == cm->name)
00573                                                 {
00574                                                         ModeLockOn.erase(it);
00575                                                         break;
00576                                                 }
00577 
00578                                         for (std::list<Anope::string>::iterator it = ModeLockOff.begin(), it_end = ModeLockOff.end(); it != it_end; ++it)
00579                                                 if (*it == cm->name)
00580                                                 {
00581                                                         ModeLockOff.erase(it);
00582                                                         break;
00583                                                 }
00584                                 }
00585 
00586                                 if (adding)
00587                                         ModeLockOn.push_back(std::make_pair(cm->name, param));
00588                                 else
00589                                         ModeLockOff.push_back(cm->name);
00590                         }
00591                 }
00592         }
00593 
00594         /* Set Bot Modes */
00595         DefaultBotModes.modes.clear();
00596         for (unsigned i = 0; i < config->BotModes.length(); ++i)
00597         {
00598                 ChannelMode *cm = ModeManager::FindChannelModeByChar(config->BotModes[i]);
00599 
00600                 if (cm && cm->type == MODE_STATUS)
00601                         DefaultBotModes.modes.insert(cm->name);
00602                 else
00603                         /* We don't know the mode yet so just use the mode char */
00604                         DefaultBotModes.modes.insert(config->BotModes[i]);
00605         }
00606 }
00607 
00608 Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0)
00609 {
00610         Anope::string n, u, h;
00611 
00612         size_t at = fh.find('@');
00613         if (at != Anope::string::npos)
00614         {
00615                 this->host = fh.substr(at + 1);
00616 
00617                 const Anope::string &nu = fh.substr(0, at);
00618 
00619                 size_t ex = nu.find('!');
00620                 if (ex != Anope::string::npos)
00621                 {
00622                         this->user = nu.substr(ex + 1);
00623                         this->nick = nu.substr(0, ex);
00624                 }
00625                 else
00626                         this->user = nu;
00627         }
00628         else
00629         {
00630                 if (fh.find('.') != Anope::string::npos || fh.find(':') != Anope::string::npos)
00631                         this->host = fh;
00632                 else
00633                         this->nick = fh;
00634         }
00635         
00636         at = this->host.find('#');
00637         if (at != Anope::string::npos)
00638         {
00639                 this->real = this->host.substr(at + 1);
00640                 this->host = this->host.substr(0, at);
00641         }
00642         
00643         /* If the mask is all *'s it will match anything, so just clear it */
00644         if (this->nick.find_first_not_of("*") == Anope::string::npos)
00645                 this->nick.clear();
00646         
00647         if (this->user.find_first_not_of("*") == Anope::string::npos)
00648                 this->user.clear();
00649         
00650         if (this->host.find_first_not_of("*") == Anope::string::npos)
00651                 this->host.clear();
00652         else
00653         {
00654                 /* Host might be a CIDR range */
00655                 size_t sl = this->host.find_last_of('/');
00656                 if (sl != Anope::string::npos)
00657                 {
00658                         const Anope::string &cidr_ip = this->host.substr(0, sl),
00659                                                 &cidr_range = this->host.substr(sl + 1);
00660                         try
00661                         {
00662                                 sockaddrs addr(cidr_ip);
00663                                 /* If we got here, cidr_ip is a valid ip */
00664 
00665                                 if (cidr_range.is_pos_number_only())
00666                                 {
00667                                         this->cidr_len = convertTo<unsigned short>(cidr_range);
00668                                         /* If we got here, cidr_len is a valid number.
00669                                          * If cidr_len is >32 (or 128) it is handled later in
00670                                          * cidr::match
00671                                          */
00672 
00673                                         this->host = cidr_ip;
00674 
00675                                         Log(LOG_DEBUG) << "Ban " << this->mask << " has cidr " << this->cidr_len;
00676                                 }
00677                         }
00678                         catch (const SocketException &) { }
00679                         catch (const ConvertException &) { }
00680                 }
00681         }
00682 
00683         if (this->real.find_first_not_of("*") == Anope::string::npos)
00684                 this->real.clear();
00685 }
00686 
00687 const Anope::string Entry::GetMask() const
00688 {
00689         return this->mask;
00690 }
00691 
00692 bool Entry::Matches(const User *u, bool full) const
00693 {
00694         /* First check if this mode has defined any matches (usually for extbans). */
00695         if (IRCD->IsExtbanValid(this->mask))
00696         {
00697                 ChannelMode *cm = ModeManager::FindChannelModeByName(this->name);
00698                 if (cm != NULL && cm->type == MODE_LIST)
00699                 {
00700                         ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
00701                         if (cml->Matches(u, this))
00702                                 return true;
00703                 }
00704         }
00705 
00706         /* If the user's displayed host is their real host, then we can do a full match without
00707          * having to worry about exposing a user's IP
00708          */
00709         full |= u->GetDisplayedHost() == u->host;
00710 
00711         bool ret = true;
00712 
00713         if (!this->nick.empty() && !Anope::Match(u->nick, this->nick))
00714                 ret = false;
00715 
00716         if (!this->user.empty() && !Anope::Match(u->GetVIdent(), this->user) && (!full || !Anope::Match(u->GetIdent(), this->user)))
00717                 ret = false;
00718 
00719         if (this->cidr_len && full)
00720         {
00721                 try
00722                 {
00723                         if (!cidr(this->host, this->cidr_len).match(u->ip))
00724                                 ret = false;
00725                 }
00726                 catch (const SocketException &)
00727                 {
00728                         ret = false;
00729                 }
00730         }
00731         else if (!this->host.empty() && !Anope::Match(u->GetDisplayedHost(), this->host) && !Anope::Match(u->GetCloakedHost(), this->host) &&
00732                 (!full || (!Anope::Match(u->host, this->host) && !Anope::Match(u->ip, this->host))))
00733                 ret = false;
00734         
00735         if (!this->real.empty() && !Anope::Match(u->realname, this->real))
00736                 ret = false;
00737         
00738         return ret;
00739 }
00740