diff options
author | Adam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864> | 2009-12-13 19:32:19 +0000 |
---|---|---|
committer | Adam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864> | 2009-12-13 19:32:19 +0000 |
commit | a7ac6a0ac712892652da6dd8696b94d4c6d3ea84 (patch) | |
tree | 9bbcf49157cfda0577c34515cb44d4462818c1da /src/modes.cpp | |
parent | 3a956c51be22f1b6f3b6808c9f56fb6b26c7dd1a (diff) |
Added in a modestacker and rewrote almost all of the remaining old mode code
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2696 5417fbe8-f217-4b02-8779-1006273d7864
Diffstat (limited to 'src/modes.cpp')
-rw-r--r-- | src/modes.cpp | 610 |
1 files changed, 504 insertions, 106 deletions
diff --git a/src/modes.cpp b/src/modes.cpp index e43596620..57780985c 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -1,7 +1,7 @@ /* Mode support * - * (C) 2009 Anope Team - * Contact us at team@anope.org + * Copyright (C) 2008-2009 Adam <Adam@anope.org> + * Copyright (C) 2008-2009 Anope Team <team@anope.org> * * Please read COPYING and README for further details. * @@ -12,6 +12,9 @@ #include "services.h" #include "modules.h" +/* List of pairs of user/channels and their stacker info */ +std::list<std::pair<void *, StackerInfo *> > ModeManager::StackerObjects; + std::map<char, UserMode *> ModeManager::UserModesByChar; std::map<UserModeName, UserMode *> ModeManager::UserModesByName; /* Channel modes */ @@ -76,139 +79,89 @@ void SetDefaultMLock() } } -/** Add a user mode to Anope - * @param Mode The mode - * @param um A UserMode or UserMode derived class - * @return true on success, false on error +/** Default constructor + * @param mName The mode name */ -bool ModeManager::AddUserMode(char Mode, UserMode *um) +UserMode::UserMode(UserModeName mName) { - um->ModeChar = Mode; - bool ret = ModeManager::UserModesByChar.insert(std::make_pair(Mode, um)).second; - if (ret) - ret = ModeManager::UserModesByName.insert(std::make_pair(um->Name, um)).second; - - if (ret) - { - FOREACH_MOD(I_OnUserModeAdd, OnUserModeAdd(um)); - } - - return ret; + this->Name = mName; + this->Type = MODE_REGULAR; } -/** Add a channel mode to Anope - * @param Mode The mode - * @param cm A ChannelMode or ChannelMode derived class - * @return true on success, false on error +/** Default destructor */ -bool ModeManager::AddChannelMode(char Mode, ChannelMode *cm) +UserMode::~UserMode() { - cm->ModeChar = Mode; - bool ret = ModeManager::ChannelModesByChar.insert(std::make_pair(Mode, cm)).second; - if (ret) - ret = ModeManager::ChannelModesByName.insert(std::make_pair(cm->Name, cm)).second; - - if (ret) - { - /* Apply this mode to the new default mlock if its used */ - SetDefaultMLock(); - - FOREACH_MOD(I_OnChannelModeAdd, OnChannelModeAdd(cm)); - } +} - return ret; +UserModeParam::UserModeParam(UserModeName mName) : UserMode(mName) +{ + this->Type = MODE_PARAM; } -/** Find a channel mode - * @param Mode The mode - * @return The mode class +/** Default constrcutor + * @param mName The mode name */ -ChannelMode *ModeManager::FindChannelModeByChar(char Mode) +ChannelMode::ChannelMode(ChannelModeName mName) { - std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.find(Mode); - - if (it != ModeManager::ChannelModesByChar.end()) - { - return it->second; - } - - return NULL; + this->Name = mName; + this->Type = MODE_REGULAR; } -/** Find a user mode - * @param Mode The mode - * @return The mode class +/** Default destructor */ -UserMode *ModeManager::FindUserModeByChar(char Mode) +ChannelMode::~ChannelMode() { - std::map<char, UserMode *>::iterator it = ModeManager::UserModesByChar.find(Mode); - - if (it != ModeManager::UserModesByChar.end()) - { - return it->second; - } - - return NULL; } -/** Find a channel mode - * @param Mode The modename - * @return The mode class +/** Default constructor + * @param mName The mode name */ -ChannelMode *ModeManager::FindChannelModeByName(ChannelModeName Name) +ChannelModeList::ChannelModeList(ChannelModeName mName) : ChannelMode(mName) { - std::map<ChannelModeName, ChannelMode *>::iterator it = ModeManager::ChannelModesByName.find(Name); - - if (it != ModeManager::ChannelModesByName.end()) - { - return it->second; - } - - return NULL; + this->Type = MODE_LIST; } -/** Find a user mode - * @param Mode The modename - * @return The mode class +/** Default destructor */ -UserMode *ModeManager::FindUserModeByName(UserModeName Name) +ChannelModeList::~ChannelModeList() { - std::map<UserModeName, UserMode *>::iterator it = ModeManager::UserModesByName.find(Name); - - if (it != ModeManager::UserModesByName.end()) - { - return it->second; - } - - return NULL; } -/** Gets the channel mode char for a symbol (eg + returns v) - * @param Value The symbol - * @return The char +/** Default constructor + * @param mName The mode name + * @param MinusArg true if the mode sends no arg when unsetting */ -char ModeManager::GetStatusChar(char Value) +ChannelModeParam::ChannelModeParam(ChannelModeName mName, bool MinusArg) : ChannelMode(mName) { - std::map<char, ChannelMode *>::iterator it; - ChannelMode *cm; - ChannelModeStatus *cms; - - for (it = ModeManager::ChannelModesByChar.begin(); it != ModeManager::ChannelModesByChar.end(); ++it) - { - cm = it->second; + this->Type = MODE_PARAM; + this->MinusNoArg = MinusArg; +} - if (cm->Type == MODE_STATUS) - { - cms = static_cast<ChannelModeStatus *>(cm); +/** Default destructor + */ +ChannelModeParam::~ChannelModeParam() +{ +} - if (Value == cms->Symbol) - { - return it->first; - } - } - } +/** Default constructor + * @param mName The mode name + * @param mStatus A CUS_ value + * @param mSymbol The symbol for the mode, eg @ % + + * @param mProtectBotServ Should botserv clients reset this on themself if it gets unset? + */ +ChannelModeStatus::ChannelModeStatus(ChannelModeName mName, int16 mStatus, char mSymbol, bool mProtectBotServ) : ChannelMode(mName) +{ + this->Type = MODE_STATUS; + this->Status = mStatus; + this->Symbol = mSymbol; + this->ProtectBotServ = mProtectBotServ; +} - return 0; +/** Default destructor + */ +ChannelModeStatus::~ChannelModeStatus() +{ } /** Is the key valid @@ -326,7 +279,6 @@ void ChannelModeBan::DelMask(Channel *chan, const char *mask) if (chan->ci && (akick = is_stuck(chan->ci, mask))) stick_mask(chan->ci, akick); - } /** Add an except to the channel @@ -432,3 +384,449 @@ void ChannelModeInvite::DelMask(Channel *chan, const char *mask) chan->name); } } + +void StackerInfo::AddMode(void *Mode, bool Set, const std::string &Param) +{ + ChannelMode *cm = NULL; + UserMode *um = NULL; + std::list<std::pair<void *, std::string> > *list, *otherlist; + std::list<std::pair<void *, std::string > >::iterator it; + + if (Type == ST_CHANNEL) + cm = static_cast<ChannelMode *>(Mode); + else if (Type == ST_USER) + um = static_cast<UserMode *>(Mode); + if (Set) + { + list = &AddModes; + otherlist = &DelModes; + } + else + { + list = &DelModes; + otherlist = &AddModes; + } + + /* Don't allow modes to be on the list twice, but only if they are + * not a list or status mode + */ + if (cm && (cm->Type != MODE_LIST && cm->Type != MODE_STATUS)) + { + /* Remove this mode from our list if it already exists */ + for (it = list->begin(); it != list->end(); ++it) + { + if (it->first == Mode) + { + list->erase(it); + /* It can't be on the list twice */ + break; + } + } + + /* Remove the mode from the other list */ + for (it = otherlist->begin(); it != otherlist->end(); ++it) + { + if (it->first == Mode) + { + otherlist->erase(it); + /* It can't be on the list twice */ + break; + } + } + } + /* This is a list mode or a status mode, or a usermode */ + else + { + /* If exactly the same thing is being set on the other list, remove it from the other list */ + it = std::find(otherlist->begin(), otherlist->end(), std::make_pair(Mode, Param)); + if (it != otherlist->end()) + { + otherlist->erase(it); + /* If it is on the other list then just return, it would alreayd be set proprely */ + return; + } + } + + /* Add this mode and its param to our list */ + list->push_back(std::make_pair(Mode, Param)); +} + +/** Get the stacker info for an item, if one doesnt exist it is created + * @param Item The user/channel etc + * @return The stacker info + */ +StackerInfo *ModeManager::GetInfo(void *Item) +{ + for (std::list<std::pair<void *, StackerInfo *> >::const_iterator it = StackerObjects.begin(); it != +StackerObjects.end(); ++it) + { + const std::pair<void *, StackerInfo *> &PItem = *it; + if (PItem.first == Item) + return PItem.second; + } + + StackerInfo *s = new StackerInfo; + StackerObjects.push_back(std::make_pair(Item, s)); + return s; +} + +/** Build a list of mode strings to send to the IRCd from the mode stacker + * @param info The stacker info for a channel or user + * @return a list of strings + */ +std::list<std::string> ModeManager::BuildModeStrings(StackerInfo *info) +{ + std::list<std::string> ret; + std::list<std::pair<void *, std::string> >::iterator it; + std::string buf, parambuf; + ChannelMode *cm = NULL; + UserMode *um = NULL; + unsigned Modes = 0; + + buf = "+"; + for (it = info->AddModes.begin(); it != info->AddModes.end(); ++it) + { + if (++Modes > 12) //XXX this number needs to be recieved from the ircd + { + ret.push_back(buf + parambuf); + buf = "+"; + parambuf.clear(); + Modes = 1; + } + + if (info->Type == ST_CHANNEL) + { + cm = static_cast<ChannelMode *>(it->first); + buf += cm->ModeChar; + } + else if (info->Type == ST_USER) + { + um = static_cast<UserMode *>(it->first); + buf += um->ModeChar; + } + + if (!it->second.empty()) + parambuf += " " + it->second; + } + + if (buf[buf.length() - 1] == '+') + buf.erase(buf.length() - 1); + + buf += "-"; + for (it = info->DelModes.begin(); it != info->DelModes.end(); ++it) + { + if (++Modes > 12) //XXX this number needs to be recieved from the ircd + { + ret.push_back(buf + parambuf); + buf = "-"; + parambuf.clear(); + Modes = 1; + } + + if (info->Type == ST_CHANNEL) + { + cm = static_cast<ChannelMode *>(it->first); + buf += cm->ModeChar; + } + else if (info->Type == ST_USER) + { + um = static_cast<UserMode *>(it->first); + buf += um->ModeChar; + } + + if (!it->second.empty()) + parambuf += " " + it->second; + } + + if (buf[buf.length() - 1] == '-') + buf.erase(buf.length() - 1); + + if (!buf.empty()) + ret.push_back(buf + parambuf); + + return ret; +} + +/** Add a mode to the stacker, internal use only + * @param bi The client to set the modes from + * @param u The user + * @param um The user mode + * @param Set Adding or removing? + * @param Param A param, if there is one + */ +void ModeManager::StackerAddInternal(BotInfo *bi, User *u, UserMode *um, bool Set, const std::string &Param) +{ + StackerAddInternal(bi, u, um, Set, Param, ST_USER); +} + +/** Add a mode to the stacker, internal use only + * @param bi The client to set the modes from + * @param c The channel + * @param cm The channel mode + * @param Set Adding or removing? + * @param Param A param, if there is one + */ +void ModeManager::StackerAddInternal(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const std::string &Param) +{ + StackerAddInternal(bi, c, cm, Set, Param, ST_CHANNEL); +} + +/** Really add a mode to the stacker, internal use only + * @param bi The client to set the modes from + * @param Object The object, user/channel + * @param Mode The mode + * @param Set Adding or removing? + * @param Param A param, if there is one + * @param Type The type this is, user or channel + */ +void ModeManager::StackerAddInternal(BotInfo *bi, void *Object, void *Mode, bool Set, const std::string &Param, StackerType Type) +{ + StackerInfo *s = GetInfo(Object); + s->Type = Type; + s->AddMode(Mode, Set, Param); + if (bi) + s->bi = bi; + else if (Type == ST_CHANNEL) + s->bi = whosends(static_cast<Channel *>(Object)->ci); + else if (Type == ST_USER) + s->bi = NULL; +} + +/** Add a user mode to Anope + * @param Mode The mode + * @param um A UserMode or UserMode derived class + * @return true on success, false on error + */ +bool ModeManager::AddUserMode(char Mode, UserMode *um) +{ + um->ModeChar = Mode; + bool ret = ModeManager::UserModesByChar.insert(std::make_pair(Mode, um)).second; + if (ret) + ret = ModeManager::UserModesByName.insert(std::make_pair(um->Name, um)).second; + + if (ret) + { + FOREACH_MOD(I_OnUserModeAdd, OnUserModeAdd(um)); + } + + return ret; +} + +/** Add a channel mode to Anope + * @param Mode The mode + * @param cm A ChannelMode or ChannelMode derived class + * @return true on success, false on error + */ +bool ModeManager::AddChannelMode(char Mode, ChannelMode *cm) +{ + cm->ModeChar = Mode; + bool ret = ModeManager::ChannelModesByChar.insert(std::make_pair(Mode, cm)).second; + if (ret) + ret = ModeManager::ChannelModesByName.insert(std::make_pair(cm->Name, cm)).second; + + if (ret) + { + /* Apply this mode to the new default mlock if its used */ + SetDefaultMLock(); + + FOREACH_MOD(I_OnChannelModeAdd, OnChannelModeAdd(cm)); + } + + return ret; +} +/** Find a channel mode + * @param Mode The mode + * @return The mode class + */ +ChannelMode *ModeManager::FindChannelModeByChar(char Mode) +{ + std::map<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.find(Mode); + + if (it != ModeManager::ChannelModesByChar.end()) + { + return it->second; + } + + return NULL; +} + +/** Find a user mode + * @param Mode The mode + * @return The mode class + */ +UserMode *ModeManager::FindUserModeByChar(char Mode) +{ + std::map<char, UserMode *>::iterator it = ModeManager::UserModesByChar.find(Mode); + + if (it != ModeManager::UserModesByChar.end()) + { + return it->second; + } + + return NULL; +} + +/** Find a channel mode + * @param Mode The modename + * @return The mode class + */ +ChannelMode *ModeManager::FindChannelModeByName(ChannelModeName Name) +{ + std::map<ChannelModeName, ChannelMode *>::iterator it = ModeManager::ChannelModesByName.find(Name); + + if (it != ModeManager::ChannelModesByName.end()) + { + return it->second; + } + + return NULL; +} + +/** Find a user mode + * @param Mode The modename + * @return The mode class + */ +UserMode *ModeManager::FindUserModeByName(UserModeName Name) +{ + std::map<UserModeName, UserMode *>::iterator it = ModeManager::UserModesByName.find(Name); + + if (it != ModeManager::UserModesByName.end()) + { + return it->second; + } + + return NULL; +} + +/** Gets the channel mode char for a symbol (eg + returns v) + * @param Value The symbol + * @return The char + */ +char ModeManager::GetStatusChar(char Value) +{ + std::map<char, ChannelMode *>::iterator it; + ChannelMode *cm; + ChannelModeStatus *cms; + + for (it = ModeManager::ChannelModesByChar.begin(); it != ModeManager::ChannelModesByChar.end(); ++it) + { + cm = it->second; + if (cm->Type == MODE_STATUS) + { + cms = static_cast<ChannelModeStatus *>(cm); + + if (Value == cms->Symbol) + { + return it->first; + } + } + } + + return 0; +} + +/** Add a mode to the stacker to be set on a channel + * @param bi The client to set the modes from + * @param c The channel + * @param cm The channel mode + * @param Set true for setting, false for removing + * @param Param The param, if there is one + */ +void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const std::string &Param) +{ + StackerAddInternal(bi, c, cm, Set, Param); +} + +/** Add a mode to the stacker to be set on a channel + * @param bi The client to set the modes from + * @param c The channel + * @param Name The channel mode name + * @param Set true for setting, false for removing + * @param Param The param, if there is one + */ +void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelModeName Name, bool Set, const std::string &Param) +{ + StackerAdd(bi, c, FindChannelModeByName(Name), Set, Param); +} + +/** Add a mode to the stacker to be set on a channel + * @param bi The client to set the modes from + * @param c The channel + * @param Mode The mode char + * @param Set true for setting, false for removing + * @param Param The param, if there is one + */ +void ModeManager::StackerAdd(BotInfo *bi, Channel *c, const char Mode, bool Set, const std::string &Param) +{ + StackerAdd(bi, c, FindChannelModeByChar(Mode), Set, Param); +} + +/** Add a mode to the stacker to be set on a user + * @param bi The client to set the modes from + * @param u The user + * @param um The user mode + * @param Set true for setting, false for removing + * @param param The param, if there is one + */ +void ModeManager::StackerAdd(BotInfo *bi, User *u, UserMode *um, bool Set, const std::string &Param) +{ + StackerAddInternal(bi, u, um, Set, Param); +} + +/** Add a mode to the stacker to be set on a user + * @param bi The client to set the modes from + * @param u The user + * @param Name The user mode name + * @param Set true for setting, false for removing + * @param Param The param, if there is one + */ +void ModeManager::StackerAdd(BotInfo *bi, User *u, UserModeName Name, bool Set, const std::string &Param) +{ + StackerAdd(bi, u, FindUserModeByName(Name), Set, Param); +} + +/** Add a mode to the stacker to be set on a user + * @param bi The client to set the modes from + * @param u The user + * @param Mode The mode to be set + * @param Set true for setting, false for removing + * @param Param The param, if there is one + */ +void ModeManager::StackerAdd(BotInfo *bi, User *u, const char Mode, bool Set, const std::string &Param) +{ + StackerAdd(bi, u, FindUserModeByChar(Mode), Set, Param); +} + +/** Process all of the modes in the stacker and send them to the IRCd to be set on channels/users + */ +void ModeManager::ProcessModes() +{ + if (!StackerObjects.empty()) + { + for (std::list<std::pair<void *, StackerInfo *> >::const_iterator it = StackerObjects.begin(); it != StackerObjects.end(); ++it) + { + StackerInfo *s = it->second; + User *u = NULL; + Channel *c = NULL; + std::list<std::string> ModeStrings = BuildModeStrings(s); + + if (s->Type == ST_USER) + u = static_cast<User *>(it->first); + else if (s->Type == ST_CHANNEL) + c = static_cast<Channel *>(it->first); + else + throw CoreException("ModeManager::ProcessModes got invalid Stacker Info type"); + + for (std::list<std::string>::iterator lit = ModeStrings.begin(); lit != ModeStrings.end(); ++lit) + { + if (c) + ircdproto->SendMode(s->bi, c->name, lit->c_str()); + else if (u) + ircdproto->SendMode(u, lit->c_str()); + } + delete it->second; + } + StackerObjects.clear(); + } +} + |