diff options
64 files changed, 752 insertions, 786 deletions
diff --git a/include/access.h b/include/access.h index ea2667774..f60625ad9 100644 --- a/include/access.h +++ b/include/access.h @@ -79,6 +79,8 @@ class CoreExport ChanAccess : public Serializable AccessProvider *provider; /* Channel this access entry is on */ Serialize::Reference<ChannelInfo> ci; + /* account this access entry is for, if any */ + Serialize::Reference<NickCore> nc; Anope::string mask; Anope::string creator; time_t last_seen; diff --git a/include/anope.h b/include/anope.h index 9bf0f982d..8e24d12da 100644 --- a/include/anope.h +++ b/include/anope.h @@ -255,7 +255,7 @@ namespace Anope { Anope::string new_string = *this; for (size_type i = 0; i < new_string.length(); ++i) - new_string[i] = std::tolower(new_string[i], Anope::casemap); + new_string[i] = Anope::tolower(new_string[i]); return new_string; } @@ -266,7 +266,7 @@ namespace Anope { Anope::string new_string = *this; for (size_type i = 0; i < new_string.length(); ++i) - new_string[i] = std::toupper(new_string[i], Anope::casemap); + new_string[i] = Anope::toupper(new_string[i]); return new_string; } @@ -547,15 +547,12 @@ class CoreExport sepstream /** Original string. */ Anope::string tokens; - /** Last position of a seperator token - */ - Anope::string::iterator last_starting_position; - /** Current string position - */ - Anope::string::iterator n; /** Seperator value */ char sep; + /** Current string position + */ + size_t pos; public: /** Create a sepstream and fill it with the provided data */ @@ -570,7 +567,7 @@ class CoreExport sepstream /** Gets token number 'num' from the stream * @param token The token is placed here * @param num The token number to featch - * @return True if the token was able to be detched + * @return True if the token was able to be fetched */ bool GetToken(Anope::string &token, int num); @@ -588,7 +585,7 @@ class CoreExport sepstream /** Gets token number 'num' from the stream and all remaining tokens. * @param token The token is placed here * @param num The token number to featch - * @return True if the token was able to be detched + * @return True if the token was able to be fetched */ bool GetTokenRemainder(Anope::string &token, int num); diff --git a/include/channels.h b/include/channels.h index 18ef65a7c..118864c8a 100644 --- a/include/channels.h +++ b/include/channels.h @@ -54,7 +54,7 @@ class CoreExport Channel : public Base, public Extensible time_t creation_time; /* Users in the channel */ - typedef std::list<ChanUserContainer *> ChanUserList; + typedef std::map<User *, ChanUserContainer *> ChanUserList; ChanUserList users; /* Current topic of the channel */ @@ -75,12 +75,14 @@ class CoreExport Channel : public Base, public Extensible int16_t chanserv_modecount; /* Number of check_mode()'s this sec */ int16_t bouncy_modes; /* Did we fail to set modes here? */ + private: /** Constructor * @param name The channel name * @param ts The time the channel was created */ Channel(const Anope::string &nname, time_t ts = Anope::CurTime); + public: /** Destructor */ ~Channel(); @@ -113,14 +115,14 @@ class CoreExport Channel : public Base, public Extensible * @param u The user * @return A user container if found, else NULL */ - ChanUserContainer *FindUser(const User *u) const; + ChanUserContainer *FindUser(User *u) const; /** Check if a user has a status on a channel * @param u The user * @param cms The status mode, or NULL to represent no status * @return true or false */ - bool HasUserStatus(const User *u, ChannelModeStatus *cms) const; + bool HasUserStatus(User *u, ChannelModeStatus *cms); /** Check if a user has a status on a channel * Use the overloaded function for ChannelModeStatus* to check for no status @@ -128,7 +130,7 @@ class CoreExport Channel : public Base, public Extensible * @param name The mode name, eg CMODE_OP, CMODE_VOICE * @return true or false */ - bool HasUserStatus(const User *u, const Anope::string &name) const; + bool HasUserStatus(User *u, const Anope::string &name); /** See if a channel has a mode * @param name The mode name @@ -279,13 +281,20 @@ class CoreExport Channel : public Base, public Extensible * @param full Whether or not to match using the user's real host and IP * @return whether or not a ban was removed */ - bool Unban(const User *u, bool full = false); + bool Unban(User *u, bool full = false); /** Finds a channel * @param name The channel to find * @return The channel, if found */ static Channel* Find(const Anope::string &name); + + /** Finds or creates a channel + * @param name The channel name + * @param created Set to true if the channel was just created + * @param ts The time the channel was created + */ + static Channel *FindOrCreate(const Anope::string &name, bool &created, time_t ts = Anope::CurTime); }; #endif // CHANNELS_H diff --git a/include/hashcomp.h b/include/hashcomp.h index 9ebc7ae81..38c0e3833 100644 --- a/include/hashcomp.h +++ b/include/hashcomp.h @@ -28,6 +28,10 @@ namespace Anope /* Casemap in use by Anope. ci::string's comparation functions use this (and thus Anope::string) */ extern std::locale casemap; + extern void CaseMapRebuild(); + extern unsigned char tolower(unsigned char); + extern unsigned char toupper(unsigned char); + /* ASCII case insensitive ctype. */ template<typename char_type> class ascii_ctype : public std::ctype<char_type> diff --git a/include/logger.h b/include/logger.h index 5050c22ce..afa874ca3 100644 --- a/include/logger.h +++ b/include/logger.h @@ -45,7 +45,8 @@ struct LogFile std::ofstream stream; LogFile(const Anope::string &name); - Anope::string GetName() const; + ~LogFile(); + const Anope::string &GetName() const; }; /* Represents a single log message */ @@ -72,7 +73,6 @@ class CoreExport Log Module *m; LogType type; Anope::string category; - std::list<Anope::string> sources; std::stringstream buf; @@ -109,17 +109,18 @@ class CoreExport Log class CoreExport LogInfo { public: - std::list<Anope::string> targets; - std::map<Anope::string, LogFile *> logfiles; - std::list<Anope::string> sources; + std::vector<Anope::string> targets; + std::vector<LogFile *> logfiles; + int last_day; + std::vector<Anope::string> sources; int log_age; - std::list<Anope::string> admin; - std::list<Anope::string> override; - std::list<Anope::string> commands; - std::list<Anope::string> servers; - std::list<Anope::string> users; - std::list<Anope::string> channels; - std::list<Anope::string> normal; + std::vector<Anope::string> admin; + std::vector<Anope::string> override; + std::vector<Anope::string> commands; + std::vector<Anope::string> servers; + std::vector<Anope::string> users; + std::vector<Anope::string> channels; + std::vector<Anope::string> normal; bool raw_io; bool debug; @@ -127,7 +128,7 @@ class CoreExport LogInfo ~LogInfo(); - void AddType(std::list<Anope::string> &list, const Anope::string &type); + void OpenLogFiles(); bool HasType(LogType ltype, const Anope::string &type) const; diff --git a/include/modes.h b/include/modes.h index bb329b5b4..6a39393bb 100644 --- a/include/modes.h +++ b/include/modes.h @@ -134,7 +134,7 @@ class CoreExport ChannelModeList : public ChannelMode * @param e The entry to match against * @return true on match */ - virtual bool Matches(const User *u, const Entry *e) { return false; } + virtual bool Matches(User *u, const Entry *e) { return false; } /** Called when a mask is added to a channel * @param chan The channel @@ -181,7 +181,7 @@ class CoreExport ChannelModeStatus : public ChannelMode { public: /* The symbol, eg @ % + */ - char Symbol; + char symbol; /* The "level" of the mode, used to compare with other modes. * Used so we know op > halfop > voice etc. */ @@ -190,10 +190,10 @@ class CoreExport ChannelModeStatus : public ChannelMode /** constructor * @param name The mode name * @param mc The mode char - * @param mSymbol The symbol for the mode, eg @ % + * @param msymbol The symbol for the mode, eg @ % * @param mlevel A level for the mode, which is usually determined by the PREFIX capab */ - ChannelModeStatus(const Anope::string &name, char mc, char mSymbol, short mlevel = 0); + ChannelModeStatus(const Anope::string &name, char mc, char msymbol, short mlevel = 0); /** destructor */ @@ -203,9 +203,14 @@ class CoreExport ChannelModeStatus : public ChannelMode /* The status a user has on a channel (+v, +h, +o) etc */ class CoreExport ChannelStatus { + Anope::string modes; public: - std::set<Anope::string> modes; - Anope::string BuildCharPrefixList() const; + void AddMode(char c); + void DelMode(char c); + bool HasMode(char c) const; + bool Empty() const; + void Clear(); + const Anope::string &Modes() const; Anope::string BuildModePrefixList() const; }; @@ -292,11 +297,14 @@ class CoreExport ModeManager */ static std::list<Anope::string> BuildModeStrings(StackerInfo *info); - public: - /* List of all modes Anope knows about */ + /* Array of all modes Anope knows about. Modes are in this array at position + * modechar. Additionally, status modes are in this array (again) at statuschar. + */ static std::vector<ChannelMode *> ChannelModes; static std::vector<UserMode *> UserModes; + public: + /* Number of generic channel and user modes we are tracking */ static unsigned GenericChannelModes; static unsigned GenericUserModes; @@ -358,6 +366,9 @@ class CoreExport ModeManager */ static char GetStatusChar(char symbol); + static const std::vector<ChannelMode *> &GetChannelModes(); + static const std::vector<UserMode *> &GetUserModes(); + /** 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 @@ -419,7 +430,7 @@ class CoreExport Entry * @param full True to match against a users real host and IP * @return true on match */ - bool Matches(const User *u, bool full = false) const; + bool Matches(User *u, bool full = false) const; }; #endif // MODES_H diff --git a/include/protocol.h b/include/protocol.h index 8953d25e5..23bed3003 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -148,7 +148,7 @@ class CoreExport IRCDProto : public Service * be set on the user. This may include the modes in the join, but will usually place them on the mode * stacker to be set "soon". */ - virtual void SendJoin(const User *u, Channel *c, const ChannelStatus *status) = 0; + virtual void SendJoin(User *u, Channel *c, const ChannelStatus *status) = 0; virtual void SendPart(const BotInfo *bi, const Channel *chan, const char *fmt, ...); /** Force joins a user that isn't ours to a channel. diff --git a/include/servers.h b/include/servers.h index d8b01626f..bf0acb523 100644 --- a/include/servers.h +++ b/include/servers.h @@ -33,6 +33,10 @@ namespace Servers */ extern CoreExport Server* GetUplink(); + /* Server maps by name and id */ + extern CoreExport Anope::map<Server *> ByName; + extern CoreExport Anope::map<Server *> ByID; + /* CAPAB/PROTOCTL given by the uplink */ extern CoreExport std::set<Anope::string> Capab; } @@ -169,10 +173,10 @@ class CoreExport Server : public Extensible /** Find a server * @param name The name or SID/numeric - * @param s The server list to search for this server on, defaults to our Uplink + * @param name_only set to true to only look up by name, not SID * @return The server */ - static Server *Find(const Anope::string &name, Server *s = NULL); + static Server *Find(const Anope::string &name, bool name_only = false); }; #endif // SERVERS_H diff --git a/include/users.h b/include/users.h index 4110ad211..5bcd61f95 100644 --- a/include/users.h +++ b/include/users.h @@ -79,7 +79,7 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe bool super_admin; /* Channels the user is in */ - typedef std::list<ChanUserContainer *> ChanUserList; + typedef std::map<Channel *, ChanUserContainer *> ChanUserList; ChanUserList chans; /* Last time this user sent a memo command used */ @@ -312,7 +312,7 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe * @param c The channel * @return The channel container, or NULL */ - ChanUserContainer *FindChannel(const Channel *c) const; + ChanUserContainer *FindChannel(Channel *c) const; /** Check if the user is protected from kicks and negative mode changes * @return true or false diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp index 3f7cc16c2..97f6b6035 100644 --- a/modules/commands/bs_kick.cpp +++ b/modules/commands/bs_kick.cpp @@ -808,7 +808,7 @@ class BSKick : public Module { Channel *c = cit->second; for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) - (*it)->Shrink("bs_main_userdata"); + it->second->Shrink("bs_main_userdata"); c->Shrink("bs_main_bandata"); } } @@ -1033,7 +1033,7 @@ class BSKick : public Module { for (User::ChanUserList::iterator it = u->chans.begin(); it != u->chans.end();) { - Channel *chan = (*it)->chan; + Channel *chan = it->second->chan; ++it; if (chan->ci && chan->ci->HasExt("BS_KICK_AMSGS") && !chan->ci->AccessFor(u).HasPriv("NOKICK")) diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 239c344ab..3a4bdff54 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -326,7 +326,7 @@ class CommandCSAccess : public Command Anope::string timebuf; if (ci->c) for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit) - if (access->Matches((*cit)->user, (*cit)->user->Account())) + if (access->Matches(cit->second->user, cit->second->user->Account())) timebuf = "Now"; if (timebuf.empty()) { @@ -360,7 +360,7 @@ class CommandCSAccess : public Command Anope::string timebuf; if (ci->c) for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit) - if (access->Matches((*cit)->user, (*cit)->user->Account())) + if (access->Matches(cit->second->user, cit->second->user->Account())) timebuf = "Now"; if (timebuf.empty()) { diff --git a/modules/commands/cs_akick.cpp b/modules/commands/cs_akick.cpp index a3133b8e9..f2bd603f9 100644 --- a/modules/commands/cs_akick.cpp +++ b/modules/commands/cs_akick.cpp @@ -390,9 +390,10 @@ class CommandCSAKick : public Command return; } - for (User::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) + for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) { - ChanUserContainer *uc = *it++; + ChanUserContainer *uc = it->second; + ++it; if (ci->CheckKick(uc->user)) ++count; diff --git a/modules/commands/cs_ban.cpp b/modules/commands/cs_ban.cpp index 06c8de95a..5aad394a3 100644 --- a/modules/commands/cs_ban.cpp +++ b/modules/commands/cs_ban.cpp @@ -160,7 +160,8 @@ class CommandCSBan : public Command int matched = 0, kicked = 0; for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;) { - ChanUserContainer *uc = *it++; + ChanUserContainer *uc = it->second; + ++it; if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target)) { diff --git a/modules/commands/cs_enforce.cpp b/modules/commands/cs_enforce.cpp index 4d5ba0242..fd5caf613 100644 --- a/modules/commands/cs_enforce.cpp +++ b/modules/commands/cs_enforce.cpp @@ -31,7 +31,7 @@ class CommandCSEnforce : public Command for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; ci->c->SetCorrectModes(uc->user, false, false); } @@ -50,7 +50,7 @@ class CommandCSEnforce : public Command std::vector<User *> users; for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; User *user = uc->user; if (user->IsProtected()) @@ -81,7 +81,7 @@ class CommandCSEnforce : public Command std::vector<User *> users; for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; User *user = uc->user; if (user->IsProtected()) @@ -113,7 +113,7 @@ class CommandCSEnforce : public Command std::vector<User *> users; for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; User *user = uc->user; if (user->IsProtected()) @@ -145,7 +145,7 @@ class CommandCSEnforce : public Command std::vector<User *> users; for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; User *user = uc->user; if (user->IsProtected()) @@ -195,7 +195,7 @@ class CommandCSEnforce : public Command /* The newer users are at the end of the list, so kick users starting from the end */ for (Channel::ChanUserList::reverse_iterator it = ci->c->users.rbegin(), it_end = ci->c->users.rend(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; User *user = uc->user; if (user->IsProtected()) diff --git a/modules/commands/cs_kick.cpp b/modules/commands/cs_kick.cpp index 03beaf0a8..870c18f0c 100644 --- a/modules/commands/cs_kick.cpp +++ b/modules/commands/cs_kick.cpp @@ -79,7 +79,8 @@ class CommandCSKick : public Command int matched = 0, kicked = 0; for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;) { - ChanUserContainer *uc = *it++; + ChanUserContainer *uc = it->second; + ++it; if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target)) { diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index 7edc4eddc..1d0f0985b 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -253,9 +253,11 @@ class CommandCSMode : public Command case '*': if (adding == -1 || !has_access) break; - for (unsigned j = 0; j < ModeManager::ChannelModes.size(); ++j) + for (unsigned j = 0; j < ModeManager::GetChannelModes().size(); ++j) { - ChannelMode *cm = ModeManager::ChannelModes[j]; + ChannelMode *cm = ModeManager::GetChannelModes()[j]; + if (!cm) + continue; if (!u || cm->CanSet(u)) { if (cm->type == MODE_REGULAR || (!adding && cm->type == MODE_PARAM)) @@ -309,9 +311,10 @@ class CommandCSMode : public Command break; } - for (Channel::ChanUserList::const_iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) + for (Channel::ChanUserList::const_iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end;) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; + ++it; AccessGroup targ_access = ci->AccessFor(uc->user); diff --git a/modules/commands/cs_seen.cpp b/modules/commands/cs_seen.cpp index 10c23dd53..66706c8fb 100644 --- a/modules/commands/cs_seen.cpp +++ b/modules/commands/cs_seen.cpp @@ -60,10 +60,10 @@ struct SeenInfo : Serializable s = anope_dynamic_static_cast<SeenInfo *>(obj); else { - /* ignore duplicate entries in the db, created by an old bug */ - s = FindInfo(snick); - if (!s) - s = new SeenInfo(); + SeenInfo* &info = database[snick]; + if (!info) + info = new SeenInfo(); + s = info; } data["nick"] >> s->nick; @@ -388,12 +388,9 @@ class CSSeen : public Module if (!u->server->IsSynced()) return; - SeenInfo *info = FindInfo(nick); + SeenInfo* &info = database[nick]; if (!info) - { - info = new SeenInfo; - database.insert(std::pair<Anope::string, SeenInfo *>(nick, info)); - } + info = new SeenInfo(); info->nick = nick; info->vhost = u->GetVIdent() + "@" + u->GetDisplayedHost(); info->type = Type; diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index cfc2c4767..67d024c9f 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -544,7 +544,8 @@ class CommandCSSetPersist : public Command /* Channel doesn't exist, create it */ if (!ci->c) { - Channel *c = new Channel(ci->name); + bool created; + Channel *c = Channel::FindOrCreate(ci->name, created); if (ci->bi) ci->bi->Join(c); } diff --git a/modules/commands/cs_suspend.cpp b/modules/commands/cs_suspend.cpp index fdfd2d55a..0ea54879e 100644 --- a/modules/commands/cs_suspend.cpp +++ b/modules/commands/cs_suspend.cpp @@ -66,7 +66,7 @@ class CommandCSSuspend : public Command for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; User *user = uc->user; if (!user->HasMode("OPER") && user->server != Me) users.push_back(user); diff --git a/modules/commands/cs_sync.cpp b/modules/commands/cs_sync.cpp index 1a02c813c..3983a52d1 100644 --- a/modules/commands/cs_sync.cpp +++ b/modules/commands/cs_sync.cpp @@ -35,7 +35,7 @@ class CommandCSSync : public Command Log(LOG_COMMAND, source, this, ci); for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) - ci->c->SetCorrectModes((*it)->user, true, false); + ci->c->SetCorrectModes(it->second->user, true, false); source.Reply(_("All user modes on \002%s\002 have been synced."), ci->name.c_str()); } diff --git a/modules/commands/cs_updown.cpp b/modules/commands/cs_updown.cpp index 27e1984d1..ecce1e51d 100644 --- a/modules/commands/cs_updown.cpp +++ b/modules/commands/cs_updown.cpp @@ -30,7 +30,7 @@ class CommandCSUp : public Command return; for (User::ChanUserList::iterator it = source.GetUser()->chans.begin(); it != source.GetUser()->chans.end(); ++it) { - Channel *c = (*it)->chan; + Channel *c = it->second->chan; c->SetCorrectModes(source.GetUser(), true, false); } } @@ -87,13 +87,10 @@ class CommandCSDown : public Command { void RemoveAll(User *u, Channel *c) { - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - { - ChannelMode *cm = ModeManager::ChannelModes[i]; - - if (cm != NULL && cm->type == MODE_STATUS) - c->RemoveMode(NULL, cm, u->nick); - } + ChanUserContainer *cu = c->FindUser(u); + if (cu != NULL) + for (size_t i = 0; i < cu->status.Modes().length(); ++i) + c->RemoveMode(NULL, ModeManager::FindChannelModeByChar(cu->status.Modes()[i]), u->GetUID()); } public: @@ -111,7 +108,7 @@ class CommandCSDown : public Command return; for (User::ChanUserList::iterator it = source.GetUser()->chans.begin(); it != source.GetUser()->chans.end(); ++it) { - Channel *c = (*it)->chan; + Channel *c = it->second->chan; RemoveAll(source.GetUser(), c); } } diff --git a/modules/commands/ns_recover.cpp b/modules/commands/ns_recover.cpp index 33a97646c..ee54f3b3f 100644 --- a/modules/commands/ns_recover.cpp +++ b/modules/commands/ns_recover.cpp @@ -62,7 +62,7 @@ class NSRecoverRequest : public IdentifyRequest { NSRecoverExtensibleInfo *ei = new NSRecoverExtensibleInfo; for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) - (*ei)[(*it)->chan->name] = (*it)->status; + (*ei)[it->first->name] = it->second->status; source.GetUser()->Extend("ns_recover_info", ei); } @@ -265,8 +265,8 @@ class NSRecover : public Module std::map<Anope::string, ChannelStatus>::iterator it = ei->find(c->name); if (it != ei->end()) { - for (std::set<Anope::string>::iterator it2 = it->second.modes.begin(), it2_end = it->second.modes.end(); it2 != it2_end; ++it2) - c->SetMode(c->ci->WhoSends(), ModeManager::FindChannelModeByName(*it2), u->GetUID()); + for (size_t i = 0; i < it->second.Modes().length(); ++i) + c->SetMode(c->ci->WhoSends(), ModeManager::FindChannelModeByChar(it->second.Modes()[i]), u->GetUID()); ei->erase(it); if (ei->empty()) diff --git a/modules/commands/os_chankill.cpp b/modules/commands/os_chankill.cpp index 3fea40043..c88011b5b 100644 --- a/modules/commands/os_chankill.cpp +++ b/modules/commands/os_chankill.cpp @@ -74,7 +74,7 @@ class CommandOSChanKill : public Command { for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) { - ChanUserContainer *uc = *it++; + ChanUserContainer *uc = it->second; if (uc->user->server == Me || uc->user->HasMode("OPER")) continue; diff --git a/modules/commands/os_dns.cpp b/modules/commands/os_dns.cpp index d690ae55a..666baefdf 100644 --- a/modules/commands/os_dns.cpp +++ b/modules/commands/os_dns.cpp @@ -214,7 +214,7 @@ class CommandOSDNS : public Command for (unsigned i = 0; i < dns_servers->size(); ++i) { DNSServer *s = dns_servers->at(i); - Server *srv = Server::Find(s->GetName()); + Server *srv = Server::Find(s->GetName(), true); ListFormatter::ListEntry entry; entry["Server"] = s->GetName(); @@ -351,7 +351,7 @@ class CommandOSDNS : public Command return; } - Server *serv = Server::Find(params[1]); + Server *serv = Server::Find(params[1], true); if (!serv || serv == Me || serv->IsJuped()) { source.Reply(_("Server %s is not linked to the network."), params[1].c_str()); @@ -411,7 +411,7 @@ class CommandOSDNS : public Command source.Reply(_("Removed server %s from zone %s."), s->GetName().c_str(), z->name.c_str()); return; } - else if (Server::Find(s->GetName())) + else if (Server::Find(s->GetName(), true)) { source.Reply(_("Server %s must be quit before it can be deleted."), s->GetName().c_str()); return; @@ -543,7 +543,7 @@ class CommandOSDNS : public Command source.Reply(_("Server %s does not exist."), params[1].c_str()); return; } - else if (!Server::Find(s->GetName())) + else if (!Server::Find(s->GetName(), true)) { source.Reply(_("Server %s is not currently linked."), s->GetName().c_str()); return; @@ -676,7 +676,7 @@ class ModuleDNS : public Module for (unsigned j = 0; j < dns_servers->size(); ++j) { DNSServer *s = dns_servers->at(j); - if (s->Pooled() && Server::Find(s->GetName())) + if (s->Pooled() && Server::Find(s->GetName(), true)) s->SetActive(true); } } diff --git a/modules/commands/os_forbid.cpp b/modules/commands/os_forbid.cpp index e3a0c42b8..a33ef66f2 100644 --- a/modules/commands/os_forbid.cpp +++ b/modules/commands/os_forbid.cpp @@ -16,60 +16,64 @@ class MyForbidService : public ForbidService { - Serialize::Checker<std::vector<ForbidData *> > forbid_data; + Serialize::Checker<std::vector<ForbidData *>[FT_SIZE]> forbid_data; public: MyForbidService(Module *m) : ForbidService(m), forbid_data("ForbidData") { } void AddForbid(ForbidData *d) anope_override { - this->forbid_data->push_back(d); + this->forbid_data[d->type].push_back(d); } void RemoveForbid(ForbidData *d) anope_override { - std::vector<ForbidData *>::iterator it = std::find(this->forbid_data->begin(), this->forbid_data->end(), d); - if (it != this->forbid_data->end()) - this->forbid_data->erase(it); + std::vector<ForbidData *>::iterator it = std::find(this->forbid_data[d->type].begin(), this->forbid_data[d->type].end(), d); + if (it != this->forbid_data[d->type].end()) + this->forbid_data[d->type].erase(it); delete d; } ForbidData *FindForbid(const Anope::string &mask, ForbidType ftype) anope_override { - const std::vector<ForbidData *> &forbids = this->GetForbids(); + const std::vector<ForbidData *> &forbids = this->forbid_data[ftype]; for (unsigned i = forbids.size(); i > 0; --i) { ForbidData *d = forbids[i - 1]; - if ((ftype == FT_NONE || ftype == d->type) && Anope::Match(mask, d->mask, false, true)) + if (Anope::Match(mask, d->mask, false, true)) return d; } return NULL; } - const std::vector<ForbidData *> &GetForbids() anope_override + std::vector<ForbidData *> GetForbids() anope_override { - for (unsigned i = this->forbid_data->size(); i > 0; --i) - { - ForbidData *d = this->forbid_data->at(i - 1); - - if (d->expires && Anope::CurTime >= d->expires) + std::vector<ForbidData *> forbids; + for (unsigned j = 0; j < FT_SIZE; ++j) + for (unsigned i = this->forbid_data[j].size(); i > 0; --i) { - Anope::string ftype = "none"; - if (d->type == FT_NICK) - ftype = "nick"; - else if (d->type == FT_CHAN) - ftype = "chan"; - else if (d->type == FT_EMAIL) - ftype = "email"; - - Log(LOG_NORMAL, "expire/forbid") << "Expiring forbid for " << d->mask << " type " << ftype; - this->forbid_data->erase(this->forbid_data->begin() + i - 1); - delete d; + ForbidData *d = this->forbid_data[j].at(i - 1); + + if (d->expires && Anope::CurTime >= d->expires) + { + Anope::string ftype = "none"; + if (d->type == FT_NICK) + ftype = "nick"; + else if (d->type == FT_CHAN) + ftype = "chan"; + else if (d->type == FT_EMAIL) + ftype = "email"; + + Log(LOG_NORMAL, "expire/forbid") << "Expiring forbid for " << d->mask << " type " << ftype; + this->forbid_data[j].erase(this->forbid_data[j].begin() + i - 1); + delete d; + } + else + forbids.push_back(d); } - } - return this->forbid_data; + return forbids; } }; @@ -93,7 +97,7 @@ class CommandOSForbid : public Command const Anope::string &command = params[0]; const Anope::string &subcommand = params.size() > 1 ? params[1] : ""; - ForbidType ftype = FT_NONE; + ForbidType ftype = FT_SIZE; if (subcommand.equals_ci("NICK")) ftype = FT_NICK; else if (subcommand.equals_ci("CHAN")) @@ -103,7 +107,7 @@ class CommandOSForbid : public Command else if (subcommand.equals_ci("REGISTER")) ftype = FT_REGISTER; - if (command.equals_ci("ADD") && params.size() > 3 && ftype != FT_NONE) + if (command.equals_ci("ADD") && params.size() > 3 && ftype != FT_SIZE) { const Anope::string &expiry = params[2][0] == '+' ? params[2] : ""; const Anope::string &entry = !expiry.empty() ? params[3] : params[2]; @@ -156,7 +160,7 @@ class CommandOSForbid : public Command Log(LOG_ADMIN, source, this) << "to add a forbid on " << entry << " of type " << subcommand; source.Reply(_("Added a forbid on %s to expire on %s."), entry.c_str(), d->expires ? Anope::strftime(d->expires).c_str() : "never"); } - else if (command.equals_ci("DEL") && params.size() > 2 && ftype != FT_NONE) + else if (command.equals_ci("DEL") && params.size() > 2 && ftype != FT_SIZE) { const Anope::string &entry = params[2]; diff --git a/modules/commands/os_forbid.h b/modules/commands/os_forbid.h index b4d1ce7ce..00827c559 100644 --- a/modules/commands/os_forbid.h +++ b/modules/commands/os_forbid.h @@ -3,11 +3,11 @@ enum ForbidType { - FT_NONE, FT_NICK, FT_CHAN, FT_EMAIL, - FT_REGISTER + FT_REGISTER, + FT_SIZE }; struct ForbidData : Serializable @@ -35,7 +35,7 @@ class ForbidService : public Service virtual ForbidData *FindForbid(const Anope::string &mask, ForbidType type) = 0; - virtual const std::vector<ForbidData *> &GetForbids() = 0; + virtual std::vector<ForbidData *> GetForbids() = 0; }; static ServiceReference<ForbidService> forbid_service("ForbidService", "forbid"); diff --git a/modules/commands/os_jupe.cpp b/modules/commands/os_jupe.cpp index fa79c9098..fbe5bac12 100644 --- a/modules/commands/os_jupe.cpp +++ b/modules/commands/os_jupe.cpp @@ -26,7 +26,7 @@ class CommandOSJupe : public Command { const Anope::string &jserver = params[0]; const Anope::string &reason = params.size() > 1 ? params[1] : ""; - Server *server = Server::Find(jserver); + Server *server = Server::Find(jserver, true); if (!IRCD->IsHostValid(jserver) || jserver.find('.') == Anope::string::npos) source.Reply(_("Please use a valid server name when juping.")); diff --git a/modules/commands/os_list.cpp b/modules/commands/os_list.cpp index f4de45203..6880bbbc0 100644 --- a/modules/commands/os_list.cpp +++ b/modules/commands/os_list.cpp @@ -44,7 +44,7 @@ class CommandOSChanList : public Command for (User::ChanUserList::iterator uit = u2->chans.begin(), uit_end = u2->chans.end(); uit != uit_end; ++uit) { - ChanUserContainer *cc = *uit; + ChanUserContainer *cc = uit->second; if (!modes.empty()) for (std::set<Anope::string>::iterator it = modes.begin(), it_end = modes.end(); it != it_end; ++it) @@ -142,7 +142,7 @@ class CommandOSUserList : public Command for (Channel::ChanUserList::iterator cuit = c->users.begin(), cuit_end = c->users.end(); cuit != cuit_end; ++cuit) { - ChanUserContainer *uc = *cuit; + ChanUserContainer *uc = cuit->second; if (!modes.empty()) for (std::set<Anope::string>::iterator it = modes.begin(), it_end = modes.end(); it != it_end; ++it) diff --git a/modules/commands/os_mode.cpp b/modules/commands/os_mode.cpp index 33387bff6..db0ac73b5 100644 --- a/modules/commands/os_mode.cpp +++ b/modules/commands/os_mode.cpp @@ -45,13 +45,13 @@ class CommandOSMode : public Command { for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; if (uc->user->HasMode("OPER")) continue; - for (std::set<Anope::string>::iterator it2 = uc->status.modes.begin(), it2_end = uc->status.modes.end(); it2 != it2_end; ++it2) - c->RemoveMode(c->ci->WhoSends(), *it2, uc->user->GetUID(), false); + for (size_t i = 0; i < uc->status.Modes().length(); ++i) + c->RemoveMode(c->ci->WhoSends(), ModeManager::FindChannelModeByChar(uc->status.Modes()[i]), uc->user->GetUID(), false); } source.Reply(_("All modes cleared on %s."), c->name.c_str()); diff --git a/modules/commands/os_noop.cpp b/modules/commands/os_noop.cpp index 9e9af1398..082294f22 100644 --- a/modules/commands/os_noop.cpp +++ b/modules/commands/os_noop.cpp @@ -28,7 +28,7 @@ class CommandOSNOOP : public Command const Anope::string &cmd = params[0]; const Anope::string &server = params[1]; - Server *s = Server::Find(server); + Server *s = Server::Find(server, true); if (s == NULL) source.Reply(_("Server %s does not exist."), server.c_str()); else if (s == Me || s->IsJuped()) diff --git a/modules/commands/os_session.cpp b/modules/commands/os_session.cpp index 1edda00d6..31846c9db 100644 --- a/modules/commands/os_session.cpp +++ b/modules/commands/os_session.cpp @@ -61,11 +61,6 @@ class MySessionService : public SessionService return this->Exceptions; } - void AddSession(Session *s) anope_override - { - this->Sessions[s->addr] = s; - } - void DelSession(Session *s) anope_override { this->Sessions.erase(s->addr); @@ -80,6 +75,18 @@ class MySessionService : public SessionService return NULL; } + SessionMap::iterator FindSessionIterator(const Anope::string &ip) + { + cidr c(ip, ip.find(':') != Anope::string::npos ? Config->SessionIPv6CIDR : Config->SessionIPv4CIDR); + return this->Sessions.find(c); + } + + Session* &FindOrCreateSession(const Anope::string &ip) + { + cidr c(ip, ip.find(':') != Anope::string::npos ? Config->SessionIPv6CIDR : Config->SessionIPv4CIDR); + return this->Sessions[c]; + } + SessionMap &GetSessions() anope_override { return this->Sessions; @@ -611,124 +618,117 @@ class OSSession : public Module CommandOSException commandosexception; ServiceReference<XLineManager> akills; - void AddSession(User *u, bool exempt) + public: + OSSession(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + exception_type("Exception", Exception::Unserialize), ss(this), commandossession(this), commandosexception(this), akills("XLineManager", "xlinemanager/sgline") { - Session *session; - try - { - session = this->ss.FindSession(u->ip); - } - catch (const SocketException &) - { + this->SetAuthor("Anope"); + this->SetPermanent(true); + + Implementation i[] = { I_OnUserConnect, I_OnPreUserLogoff }; + ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + ModuleManager::SetPriority(this, PRIORITY_FIRST); + } + + void OnUserConnect(User *u, bool &exempt) anope_override + { + if (u->Quitting() || !Config->LimitSessions || exempt || !u->server || u->server->IsULined()) return; - } - if (session) + try { - bool kill = false; - if (Config->DefSessionLimit && session->count >= Config->DefSessionLimit) + Session* &session = this->ss.FindOrCreateSession(u->ip); + + if (session) { - kill = true; - Exception *exception = this->ss.FindException(u); - if (exception) + bool kill = false; + if (Config->DefSessionLimit && session->count >= Config->DefSessionLimit) { - kill = false; - if (exception->limit && session->count >= exception->limit) - kill = true; + kill = true; + Exception *exception = this->ss.FindException(u); + if (exception) + { + kill = false; + if (exception->limit && session->count >= exception->limit) + kill = true; + } } - } - /* Previously on IRCds that send a QUIT (InspIRCD) when a user is killed, the session for a host was - * decremented in do_quit, which caused problems and fixed here - * - * Now, we create the user struture before calling this to fix some user tracking issues, - * so we must increment this here no matter what because it will either be - * decremented in do_kill or in do_quit - Adam - */ - ++session->count; + /* Previously on IRCds that send a QUIT (InspIRCD) when a user is killed, the session for a host was + * decremented in do_quit, which caused problems and fixed here + * + * Now, we create the user struture before calling this to fix some user tracking issues, + * so we must increment this here no matter what because it will either be + * decremented in do_kill or in do_quit - Adam + */ + ++session->count; - if (kill && !exempt) - { - if (OperServ) + if (kill && !exempt) { - if (!Config->SessionLimitExceeded.empty()) - u->SendMessage(OperServ, Config->SessionLimitExceeded.c_str(), u->ip.c_str()); - if (!Config->SessionLimitDetailsLoc.empty()) - u->SendMessage(OperServ, "%s", Config->SessionLimitDetailsLoc.c_str()); - } + if (OperServ) + { + if (!Config->SessionLimitExceeded.empty()) + u->SendMessage(OperServ, Config->SessionLimitExceeded.c_str(), u->ip.c_str()); + if (!Config->SessionLimitDetailsLoc.empty()) + u->SendMessage(OperServ, "%s", Config->SessionLimitDetailsLoc.c_str()); + } - ++session->hits; - if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && akills) - { - const Anope::string &akillmask = "*@" + u->ip; - XLine *x = new XLine(akillmask, Config->OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, "Session limit exceeded", XLineManager::GenerateUID()); - akills->AddXLine(x); - akills->Send(NULL, x); - Log(OperServ, "akill/session") << "Added a temporary AKILL for \002" << akillmask << "\002 due to excessive connections"; - } - else - { - u->Kill(Config->OperServ, "Session limit exceeded"); - u = NULL; /* No guarentee u still exists */ + ++session->hits; + if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && akills) + { + const Anope::string &akillmask = "*@" + u->ip; + XLine *x = new XLine(akillmask, Config->OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, "Session limit exceeded", XLineManager::GenerateUID()); + akills->AddXLine(x); + akills->Send(NULL, x); + Log(OperServ, "akill/session") << "Added a temporary AKILL for \002" << akillmask << "\002 due to excessive connections"; + } + else + { + u->Kill(Config->OperServ, "Session limit exceeded"); + } } } + else + { + session = new Session(u->ip, u->ip.find(':') != Anope::string::npos ? Config->SessionIPv6CIDR : Config->SessionIPv4CIDR); + } } - else - { - session = new Session(u->ip, u->ip.find(':') != Anope::string::npos ? Config->SessionIPv6CIDR : Config->SessionIPv4CIDR); - this->ss.AddSession(session); - } + catch (const SocketException &) { } } - void DelSession(User *u) + void OnPreUserLogoff(User *u) anope_override { - Session *session; + if (!Config->LimitSessions || !u->server || u->server->IsULined()) + return; + + SessionService::SessionMap::iterator sit; try { - session = this->ss.FindSession(u->ip); + sit = this->ss.FindSessionIterator(u->ip); } catch (const SocketException &) { return; } - if (!session) + + SessionService::SessionMap &sessions = this->ss.GetSessions(); + + if (sit == sessions.end()) { Log(LOG_DEBUG) << "Tried to delete non-existant session: " << u->ip; return; } + Session *session = sit->second; + if (session->count > 1) { --session->count; return; } - this->ss.DelSession(session); delete session; - } - - public: - OSSession(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), - exception_type("Exception", Exception::Unserialize), ss(this), commandossession(this), commandosexception(this), akills("XLineManager", "xlinemanager/sgline") - { - this->SetAuthor("Anope"); - this->SetPermanent(true); - - Implementation i[] = { I_OnUserConnect, I_OnPreUserLogoff }; - ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - ModuleManager::SetPriority(this, PRIORITY_FIRST); - } - - void OnUserConnect(User *user, bool &exempt) anope_override - { - if (!user->Quitting() && Config->LimitSessions) - this->AddSession(user, exempt); - } - - void OnPreUserLogoff(User *u) anope_override - { - if (Config->LimitSessions && (!u->server || !u->server->IsULined())) - this->DelSession(u); + sessions.erase(sit); } }; diff --git a/modules/commands/os_session.h b/modules/commands/os_session.h index 6d1dd917d..f3077d0ac 100644 --- a/modules/commands/os_session.h +++ b/modules/commands/os_session.h @@ -42,11 +42,7 @@ class SessionService : public Service virtual ExceptionVector &GetExceptions() = 0; - virtual void AddSession(Session *s) = 0; - - virtual void DelSession(Session *s) = 0; - - virtual Session *FindSession(const Anope::string &mask) = 0; + virtual Session *FindSession(const Anope::string &ip) = 0; virtual SessionMap &GetSessions() = 0; }; diff --git a/modules/commands/os_sxline.cpp b/modules/commands/os_sxline.cpp index 2a98edf1d..e76a611db 100644 --- a/modules/commands/os_sxline.cpp +++ b/modules/commands/os_sxline.cpp @@ -599,7 +599,7 @@ class CommandOSSQLine : public CommandOSSXLineBase std::vector<User *> users; for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; User *user = uc->user; if (!user->HasMode("OPER") && user->server != Me) diff --git a/modules/extra/cs_statusupdate.cpp b/modules/extra/cs_statusupdate.cpp index 97faae851..4a53956d7 100644 --- a/modules/extra/cs_statusupdate.cpp +++ b/modules/extra/cs_statusupdate.cpp @@ -36,7 +36,7 @@ class StatusUpdate : public Module if (ci->c) for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - User *user = (*it)->user; + User *user = it->second->user; if (access->Matches(user, user->Account())) { @@ -53,7 +53,7 @@ class StatusUpdate : public Module if (ci->c) for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - User *user = (*it)->user; + User *user = it->second->user; if (access->Matches(user, user->Account())) { diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index e4b761cc7..9166f27df 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -174,7 +174,7 @@ class MyXMLRPCEvent : public XMLRPCEvent Anope::string users; for (Channel::ChanUserList::const_iterator it = c->users.begin(); it != c->users.end(); ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; users += uc->status.BuildModePrefixList() + uc->user->nick + " "; } if (!users.empty()) @@ -226,7 +226,7 @@ class MyXMLRPCEvent : public XMLRPCEvent Anope::string channels; for (User::ChanUserList::const_iterator it = u->chans.begin(); it != u->chans.end(); ++it) { - ChanUserContainer *cc = *it; + ChanUserContainer *cc = it->second; channels += cc->status.BuildModePrefixList() + cc->chan->name + " "; } if (!channels.empty()) diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 8c2c131a6..1f15e3c06 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -143,16 +143,14 @@ class BahamutIRCdProto : public IRCDProto return; /* ZLine if we can instead */ - try - { - if (x->GetUser() == "*") + if (x->GetUser() == "*" && x->GetHost().find_first_not_of("0123456789:.") == Anope::string::npos) + try { sockaddrs(x->GetHost()); IRCD->SendSZLineDel(x); return; } - } - catch (const SocketException &) { } + catch (const SocketException &) { } UplinkSocket::Message() << "RAKILL " << x->GetHost() << " " << x->GetUser(); } @@ -170,7 +168,7 @@ class BahamutIRCdProto : public IRCDProto } /* JOIN - SJOIN */ - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { UplinkSocket::Message(user) << "SJOIN " << c->creation_time << " " << c->name; if (status) @@ -182,12 +180,11 @@ class BahamutIRCdProto : public IRCDProto */ ChanUserContainer *uc = c->FindUser(user); if (uc != NULL) - uc->status.modes.clear(); + uc->status.Clear(); BotInfo *setter = BotInfo::Find(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - if (cs.modes.count(ModeManager::ChannelModes[i]->name)) - c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false); + for (size_t i = 0; i < cs.Modes().length(); ++i) + c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); } } @@ -217,16 +214,14 @@ class BahamutIRCdProto : public IRCDProto } /* ZLine if we can instead */ - try - { - if (x->GetUser() == "*") + if (x->GetUser() == "*" && x->GetHost().find_first_not_of("0123456789:.") == Anope::string::npos) + try { sockaddrs(x->GetHost()); IRCD->SendSZLine(u, x); return; } - } - catch (const SocketException &) { } + catch (const SocketException &) { } // Calculate the time left before this would expire, capping it at 2 days time_t timeleft = x->expires - Anope::CurTime; @@ -448,14 +443,7 @@ struct IRCDMessageSJoin : IRCDMessage for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));) { buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - if (!cm) - { - Log() << "Received unknown mode prefix " << cm << " in SJOIN string"; - continue; - } - - sju.first.modes.insert(cm->name); + sju.first.AddMode(ch); } sju.second = User::Find(buf); diff --git a/modules/protocol/charybdis.cpp b/modules/protocol/charybdis.cpp index 6f41abcc5..e91478c7f 100644 --- a/modules/protocol/charybdis.cpp +++ b/modules/protocol/charybdis.cpp @@ -52,7 +52,7 @@ class CharybdisProto : public IRCDProto void SendAkill(User *u, XLine *x) anope_override { ratbox->SendAkill(u, x); } void SendAkillDel(const XLine *x) anope_override { ratbox->SendAkillDel(x); } void SendSQLineDel(const XLine *x) anope_override { ratbox->SendSQLineDel(x); } - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override { ratbox->SendJoin(user, c, status); } + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { ratbox->SendJoin(user, c, status); } void SendServer(const Server *server) anope_override { ratbox->SendServer(server); } void SendChannel(Channel *c) anope_override { ratbox->SendChannel(c); } void SendTopic(BotInfo *bi, Channel *c) anope_override { ratbox->SendTopic(bi, c); } diff --git a/modules/protocol/hybrid.cpp b/modules/protocol/hybrid.cpp index ac3f88c41..3247787f1 100644 --- a/modules/protocol/hybrid.cpp +++ b/modules/protocol/hybrid.cpp @@ -88,7 +88,7 @@ class HybridProto : public IRCDProto UplinkSocket::Message(OperServ) << "UNRESV * " << x->mask; } - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { /* * Note that we must send our modes with the SJOIN and @@ -234,7 +234,7 @@ class HybridProto : public IRCDProto { ChannelStatus status; - status.modes.insert("OP"); + status.AddMode('o'); bi->Join(c, &status); } @@ -271,24 +271,14 @@ struct IRCDMessageBMask : IRCDMessage void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = Channel::Find(params[1]); + ChannelMode *mode = ModeManager::FindChannelModeByChar(params[2][0]); - if (c) + if (c && mode) { - ChannelMode *ban = ModeManager::FindChannelModeByName("BAN"), - *except = ModeManager::FindChannelModeByName("EXCEPT"), - *invex = ModeManager::FindChannelModeByName("INVITEOVERRIDE"); - spacesepstream bans(params[3]); Anope::string token; while (bans.GetToken(token)) - { - if (ban && params[2].equals_cs("b")) - c->SetModeInternal(source, ban, token); - else if (except && params[2].equals_cs("e")) - c->SetModeInternal(source, except, token); - else if (invex && params[2].equals_cs("I")) - c->SetModeInternal(source, invex, token); - } + c->SetModeInternal(source, mode, token); } } }; @@ -412,15 +402,7 @@ struct IRCDMessageSJoin : IRCDMessage for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));) { buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - - if (!cm) - { - Log() << "Received unknown mode prefix " << ch << " in SJOIN string"; - continue; - } - - sju.first.modes.insert(cm->name); + sju.first.AddMode(ch); } sju.second = User::Find(buf); diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index 0761f478c..b6cb905c2 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -80,16 +80,14 @@ class InspIRCdProto : public IRCDProto return; /* ZLine if we can instead */ - try - { - if (x->GetUser() == "*") + if (x->GetUser() == "*" && x->GetHost().find_first_not_of("0123456789:.") == Anope::string::npos) + try { sockaddrs(x->GetHost()); IRCD->SendSZLineDel(x); return; } - } - catch (const SocketException &) { } + catch (const SocketException &) { } UplinkSocket::Message(OperServ) << "GLINE " << x->mask; } @@ -136,16 +134,14 @@ class InspIRCdProto : public IRCDProto } /* ZLine if we can instead */ - try - { - if (x->GetUser() == "*") + if (x->GetUser() == "*" && x->GetHost().find_first_not_of("0123456789:.") == Anope::string::npos) + try { sockaddrs(x->GetHost()); IRCD->SendSZLine(u, x); return; } - } - catch (const SocketException &) { } + catch (const SocketException &) { } // Calculate the time left before this would expire, capping it at 2 days time_t timeleft = x->expires - Anope::CurTime; @@ -203,7 +199,7 @@ class InspIRCdProto : public IRCDProto } /* JOIN */ - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { UplinkSocket::Message(user) << "JOIN " << c->name << " " << c->creation_time; if (status) @@ -215,12 +211,11 @@ class InspIRCdProto : public IRCDProto */ ChanUserContainer *uc = c->FindUser(user); if (uc != NULL) - uc->status.modes.clear(); + uc->status.Clear(); BotInfo *setter = BotInfo::Find(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - if (cs.modes.count(ModeManager::ChannelModes[i]->name)) - c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false); + for (size_t i = 0; i < cs.Modes().length(); ++i) + c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); } } @@ -653,7 +648,7 @@ struct IRCDMessageFJoin : IRCDMessage continue; } - sju.first.modes.insert(cm->name); + sju.first.AddMode(cm->mchar); } /* Erase the , */ buf.erase(buf.begin()); diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index a79edf291..deb7bbbf1 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -180,16 +180,15 @@ class InspIRCd12Proto : public IRCDProto } /* ZLine if we can instead */ - try - { - if (x->GetUser() == "*") + if (x->GetUser() == "*" && x->GetHost().find_first_not_of("0123456789:.") == Anope::string::npos) + try { sockaddrs(x->GetHost()); IRCD->SendSZLine(u, x); return; } - } - catch (const SocketException &) { } + catch (const SocketException &) { } + SendAddLine("G", x->GetUser() + "@" + x->GetHost(), timeleft, x->by, x->GetReason()); } @@ -221,7 +220,7 @@ class InspIRCd12Proto : public IRCDProto } /* JOIN */ - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :," << user->GetUID(); /* Note that we can send this with the FJOIN but choose not to @@ -237,19 +236,11 @@ class InspIRCd12Proto : public IRCDProto */ ChanUserContainer *uc = c->FindUser(user); if (uc != NULL) - uc->status.modes.clear(); + uc->status.Clear(); BotInfo *setter = BotInfo::Find(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - { - ChannelMode *cm = ModeManager::ChannelModes[i]; - - if (cs.modes.count(cm->name) || cs.modes.count(cm->mchar)) - { - c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false); - cs.modes.insert(cm->name); - } - } + for (size_t i = 0; i < cs.Modes().length(); ++i) + c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); } } @@ -386,7 +377,7 @@ class InspIRCdExtBan : public ChannelModeList public: InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { } - bool Matches(const User *u, const Entry *e) anope_override + bool Matches(User *u, const Entry *e) anope_override { const Anope::string &mask = e->GetMask(); @@ -839,20 +830,14 @@ struct IRCDMessageFJoin : IRCDMessage Message::Join::SJoinUser sju; /* Loop through prefixes and find modes for them */ - for (char c; (c = buf[0]) != ',';) + for (char c; (c = buf[0]) != ',' && c;) { buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(c); - if (!cm) - { - Log() << "Received unknown mode prefix " << c << " in FJOIN string"; - continue; - } - - sju.first.modes.insert(cm->name); + sju.first.AddMode(c); } /* Erase the , */ - buf.erase(buf.begin()); + if (!buf.empty()) + buf.erase(buf.begin()); sju.second = User::Find(buf); if (!sju.second) diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index bbe069466..0af696bf0 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -55,7 +55,7 @@ class InspIRCd20Proto : public IRCDProto void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) anope_override { insp12->SendModeInternal(bi, u, buf); } void SendClientIntroduction(const User *u) anope_override { insp12->SendClientIntroduction(u); } void SendServer(const Server *server) anope_override { insp12->SendServer(server); } - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override { insp12->SendJoin(user, c, status); } + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { insp12->SendJoin(user, c, status); } void SendSQLineDel(const XLine *x) anope_override { insp12->SendSQLineDel(x); } void SendSQLine(User *u, const XLine *x) anope_override { insp12->SendSQLine(u, x); } void SendVhost(User *u, const Anope::string &vident, const Anope::string &vhost) anope_override { insp12->SendVhost(u, vident, vhost); } @@ -80,7 +80,7 @@ class InspIRCdExtBan : public ChannelModeList public: InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { } - bool Matches(const User *u, const Entry *e) anope_override + bool Matches(User *u, const Entry *e) anope_override { const Anope::string &mask = e->GetMask(); @@ -111,7 +111,7 @@ class InspIRCdExtBan : public ChannelModeList { ChanUserContainer *uc = c->FindUser(u); if (uc != NULL) - if (cm == NULL || uc->status.modes.count(cm->name)) + if (cm == NULL || uc->status.HasMode(cm->mchar)) return true; } } diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp index e54a4f8f7..ef226f87e 100644 --- a/modules/protocol/ngircd.cpp +++ b/modules/protocol/ngircd.cpp @@ -83,7 +83,7 @@ class ngIRCdProto : public IRCDProto UplinkSocket::Message(Me) << "WALLOPS :" << buf; } - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { UplinkSocket::Message(user) << "JOIN " << c->name; if (status) @@ -95,12 +95,11 @@ class ngIRCdProto : public IRCDProto */ ChanUserContainer *uc = c->FindUser(user); if (uc != NULL) - uc->status.modes.clear(); + uc->status.Clear(); BotInfo *setter = BotInfo::Find(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - if (cs.modes.count(ModeManager::ChannelModes[i]->name)) - c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false); + for (size_t i = 0; i < cs.Modes().length(); ++i) + c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); } } @@ -245,10 +244,8 @@ struct IRCDMessageChaninfo : IRCDMessage */ void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - - Channel *c = Channel::Find(params[0]); - if (!c) - c = new Channel(params[0]); + bool created; + Channel *c = Channel::FindOrCreate(params[0], created); Anope::string modes = params[1]; @@ -470,15 +467,8 @@ struct IRCDMessageNJoin : IRCDMessage /* Get prefixes from the nick */ for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));) { - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); buf.erase(buf.begin()); - if (!cm) - { - Log(LOG_DEBUG) << "Received unknown mode prefix " << ch << " in NJOIN string."; - continue; - } - - sju.first.modes.insert(cm->name); + sju.first.AddMode(ch); } sju.second = User::Find(buf); diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index d117389e7..c22c43192 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -48,7 +48,7 @@ class PlexusProto : public IRCDProto void SendSVSHold(const Anope::string &nick) anope_override { hybrid->SendSVSHold(nick); } void SendSVSHoldDel(const Anope::string &nick) anope_override { hybrid->SendSVSHoldDel(nick); } - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " +" << c->GetModes(true, true) << " :" << user->GetUID(); if (status) @@ -60,12 +60,11 @@ class PlexusProto : public IRCDProto */ ChanUserContainer *uc = c->FindUser(user); if (uc != NULL) - uc->status.modes.clear(); + uc->status.Clear(); BotInfo *setter = BotInfo::Find(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - if (cs.modes.count(ModeManager::ChannelModes[i]->name)) - c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false); + for (size_t i = 0; i < cs.Modes().length(); ++i) + c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); } } diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index 247b8777a..129752c06 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -37,7 +37,7 @@ class RatboxProto : public IRCDProto void SendAkill(User *u, XLine *x) anope_override { hybrid->SendAkill(u, x); } void SendAkillDel(const XLine *x) anope_override { hybrid->SendAkillDel(x); } void SendSQLineDel(const XLine *x) anope_override { hybrid->SendSQLineDel(x); } - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override { hybrid->SendJoin(user, c, status); } + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { hybrid->SendJoin(user, c, status); } void SendServer(const Server *server) anope_override { hybrid->SendServer(server); } void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) anope_override { hybrid->SendModeInternal(bi, u, buf); } void SendChannel(Channel *c) anope_override { hybrid->SendChannel(c); } diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index 984277c14..25094a24d 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -44,16 +44,14 @@ class UnrealIRCdProto : public IRCDProto return; /* ZLine if we can instead */ - try - { - if (x->GetUser() == "*") + if (x->GetUser() == "*" && x->GetHost().find_first_not_of("0123456789:.") == Anope::string::npos) + try { sockaddrs(x->GetHost()); IRCD->SendSZLineDel(x); return; } - } - catch (const SocketException &) { } + catch (const SocketException &) { } UplinkSocket::Message() << "TKL - G " << x->GetUser() << " " << x->GetHost() << " " << Config->OperServ; } @@ -108,16 +106,14 @@ class UnrealIRCdProto : public IRCDProto } /* ZLine if we can instead */ - try - { - if (x->GetUser() == "*") + if (x->GetUser() == "*" && x->GetHost().find_first_not_of("0123456789:.") == Anope::string::npos) + try { sockaddrs(x->GetHost()); IRCD->SendSZLine(u, x); return; } - } - catch (const SocketException &) { } + catch (const SocketException &) { } // Calculate the time left before this would expire, capping it at 2 days time_t timeleft = x->expires - Anope::CurTime; @@ -154,7 +150,7 @@ class UnrealIRCdProto : public IRCDProto } /* JOIN */ - void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override + void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " :" << user->nick; if (status) @@ -166,12 +162,11 @@ class UnrealIRCdProto : public IRCDProto */ ChanUserContainer *uc = c->FindUser(user); if (uc != NULL) - uc->status.modes.clear(); + uc->status.Clear(); BotInfo *setter = BotInfo::Find(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - if (cs.modes.count(ModeManager::ChannelModes[i]->name)) - c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false); + for (size_t i = 0; i < cs.Modes().length(); ++i) + c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); } } @@ -384,7 +379,7 @@ class UnrealExtBan : public ChannelModeList public: UnrealExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { } - bool Matches(const User *u, const Entry *e) anope_override + bool Matches(User *u, const Entry *e) anope_override { const Anope::string &mask = e->GetMask(); @@ -407,7 +402,7 @@ class UnrealExtBan : public ChannelModeList { ChanUserContainer *uc = c->FindUser(u); if (uc != NULL) - if (cm == NULL || uc->status.modes.count(cm->name)) + if (cm == NULL || uc->status.HasMode(cm->mchar)) return true; } } @@ -1050,15 +1045,8 @@ struct IRCDMessageSJoin : IRCDMessage /* Get prefixes from the nick */ for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));) { + sju.first.AddMode(ch); buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - if (!cm) - { - Log(LOG_DEBUG) << "Received unknown mode prefix " << ch << " in SJOIN string"; - continue; - } - - sju.first.modes.insert(cm->name); } sju.second = User::Find(buf); diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp index 7b59c0597..21a2f75f7 100644 --- a/modules/pseudoclients/chanserv.cpp +++ b/modules/pseudoclients/chanserv.cpp @@ -35,8 +35,8 @@ class ExpireCallback : public Timer if (ci->c) { time_t last_used = ci->last_used; - for (User::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end && last_used == ci->last_used; ++cit) - ci->AccessFor((*cit)->user); + for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end && last_used == ci->last_used; ++cit) + ci->AccessFor(cit->second->user); expire = last_used == ci->last_used; } else diff --git a/modules/pseudoclients/memoserv.cpp b/modules/pseudoclients/memoserv.cpp index 73dd48b94..d28774e34 100644 --- a/modules/pseudoclients/memoserv.cpp +++ b/modules/pseudoclients/memoserv.cpp @@ -81,7 +81,7 @@ class MyMemoServService : public MemoServService { for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) { - ChanUserContainer *cu = *it; + ChanUserContainer *cu = it->second; if (ci->AccessFor(cu->user).HasPriv("MEMO")) { @@ -171,7 +171,7 @@ class MemoServCore : public Module void OnJoinChannel(User *u, Channel *c) anope_override { - if (c->ci && c->ci->AccessFor(u).HasPriv("MEMO") && c->ci->memos.memos->size() > 0) + if (c->ci && !c->ci->memos.memos->empty() && c->ci->AccessFor(u).HasPriv("MEMO")) { if (c->ci->memos.memos->size() == 1) u->SendMessage(MemoServ, _("There is \002%d\002 memo on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str()); diff --git a/modules/pseudoclients/nickserv.cpp b/modules/pseudoclients/nickserv.cpp index e221c19c0..35319e552 100644 --- a/modules/pseudoclients/nickserv.cpp +++ b/modules/pseudoclients/nickserv.cpp @@ -257,7 +257,7 @@ class NickServCore : public Module if (Config->NSModeOnID) for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) { - ChanUserContainer *cc = *it; + ChanUserContainer *cc = it->second; Channel *c = cc->chan; if (c) c->SetCorrectModes(u, true, true); @@ -296,7 +296,7 @@ class NickServCore : public Module { for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) { - ChanUserContainer *cc = *it; + ChanUserContainer *cc = it->second; Channel *c = cc->chan; if (c) c->SetCorrectModes(u, true, true); diff --git a/modules/pseudoclients/operserv.cpp b/modules/pseudoclients/operserv.cpp index 10908ef03..b2463dc4f 100644 --- a/modules/pseudoclients/operserv.cpp +++ b/modules/pseudoclients/operserv.cpp @@ -35,19 +35,7 @@ class SGLineManager : public XLineManager void SendDel(XLine *x) anope_override { - try - { - if (!IRCD->CanSZLine) - throw SocketException("SZLine is not supported"); - else if (x->GetUser() != "*") - throw SocketException("Can not ZLine a username"); - sockaddrs(x->GetHost()); - IRCD->SendSZLineDel(x); - } - catch (const SocketException &) - { - IRCD->SendAkillDel(x); - } + IRCD->SendAkillDel(x); } bool Check(User *u, const XLine *x) anope_override @@ -70,7 +58,7 @@ class SGLineManager : public XLineManager if (!x->GetReal().empty() && !Anope::Match(u->realname, x->GetReal())) return false; - if (!x->GetHost().empty()) + if (x->GetHost().find('/') != Anope::string::npos) { try { @@ -82,7 +70,7 @@ class SGLineManager : public XLineManager catch (const SocketException &) { } } - if (x->GetHost().empty() || Anope::Match(u->host, x->GetHost())) + if (x->GetHost().empty() || Anope::Match(u->host, x->GetHost()) || Anope::Match(u->ip, x->GetHost())) return true; return false; diff --git a/src/access.cpp b/src/access.cpp index dd5881108..7a178b446 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -152,18 +152,18 @@ Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data) return access; } -bool ChanAccess::Matches(const User *u, const NickCore *nc) const +bool ChanAccess::Matches(const User *u, const NickCore *acc) const { bool is_mask = this->mask.find_first_of("!@?*") != Anope::string::npos; if (u && is_mask && Anope::Match(u->nick, this->mask)) return true; else if (u && Anope::Match(u->GetDisplayedMask(), this->mask)) return true; - else if (nc) - for (unsigned i = nc->aliases->size(); i > 0; --i) + else if (acc) + for (unsigned i = 0; i < acc->aliases->size(); ++i) { - const NickAlias *na = nc->aliases->at(i - 1); - if (na && Anope::Match(na->nick, this->mask)) + const NickAlias *na = acc->aliases->at(i); + if (Anope::Match(na->nick, this->mask)) return true; } return false; diff --git a/src/bots.cpp b/src/bots.cpp index 698a37f4e..f1a96eacf 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -224,8 +224,8 @@ void BotInfo::Join(Channel *c, ChannelStatus *status) void BotInfo::Join(const Anope::string &chname, ChannelStatus *status) { - Channel *c = Channel::Find(chname); - return this->Join(c ? c : new Channel(chname), status); + bool c; + return this->Join(Channel::FindOrCreate(chname, c), status); } void BotInfo::Part(Channel *c, const Anope::string &reason) diff --git a/src/channels.cpp b/src/channels.cpp index 8e4074352..f3a061e94 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -33,11 +33,6 @@ Channel::Channel(const Anope::string &nname, time_t ts) this->name = nname; - size_t old = ChannelList.size(); - ChannelList[this->name] = this; - if (old == ChannelList.size()) - Log(LOG_DEBUG) << "Duplicate channel " << this->name << " in table?"; - this->creation_time = ts; this->server_modetime = this->chanserv_modetime = 0; this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_ts = this->topic_time = 0; @@ -46,7 +41,8 @@ Channel::Channel(const Anope::string &nname, time_t ts) if (this->ci) this->ci->c = this; - Log(NULL, this, "create"); + if (Me->IsSynced()) + Log(NULL, this, "create"); FOREACH_MOD(I_OnChannelCreate, OnChannelCreate(this)); } @@ -57,7 +53,8 @@ Channel::~Channel() ModeManager::StackerDel(this); - Log(NULL, this, "destroy"); + if (Me->IsSynced()) + Log(NULL, this, "destroy"); if (this->ci) this->ci->c = NULL; @@ -71,27 +68,20 @@ void Channel::Reset() for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it) { - ChanUserContainer *uc = *it; + ChanUserContainer *uc = it->second; ChannelStatus f = uc->status; - uc->status.modes.clear(); + uc->status.Clear(); if (BotInfo::Find(uc->user->nick)) - { - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - { - ChannelMode *cm = ModeManager::ChannelModes[i]; - - if (f.modes.count(cm->name)) - this->SetMode(NULL, cm, uc->user->GetUID(), false); - } - } + for (size_t i = 0; i < f.Modes().length(); ++i) + this->SetMode(NULL, ModeManager::FindChannelModeByName(f.Modes()[i]), uc->user->GetUID(), false); } this->CheckModes(); for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it) - this->SetCorrectModes((*it)->user, true, false); + this->SetCorrectModes(it->second->user, true, false); if (this->ci && Me && Me->IsSynced()) this->ci->RestoreTopic(); @@ -99,7 +89,7 @@ void Channel::Reset() void Channel::Sync() { - if (!this->HasMode("PERM") && (this->users.empty() || (this->users.size() == 1 && this->ci && this->ci->bi && *this->ci->bi == this->users.front()->user))) + if (!this->HasMode("PERM") && (this->users.empty() || (this->users.size() == 1 && this->ci && this->ci->bi && *this->ci->bi == this->users.begin()->second->user))) { this->Hold(); } @@ -175,11 +165,12 @@ void Channel::CheckModes() ChanUserContainer* Channel::JoinUser(User *user) { - Log(user, this, "join"); + if (user->server->IsSynced()) + Log(user, this, "join"); ChanUserContainer *cuc = new ChanUserContainer(user, this); - user->chans.push_back(cuc); - this->users.push_back(cuc); + user->chans[this] = cuc; + this->users[user] = cuc; if (this->ci && this->ci->HasExt("PERSIST") && this->creation_time > this->ci->time_registered) { @@ -194,31 +185,18 @@ ChanUserContainer* Channel::JoinUser(User *user) void Channel::DeleteUser(User *user) { - Log(user, this, "leave"); + if (user->server->IsSynced() && !user->Quitting()) + Log(user, this, "leave"); + FOREACH_MOD(I_OnLeaveChannel, OnLeaveChannel(user, this)); - ChanUserContainer *cul; - ChanUserList::iterator cit, cit_end; - for (cit = this->users.begin(), cit_end = this->users.end(); cit != cit_end && (*cit)->user != user; ++cit); - if (cit == cit_end) - { + ChanUserContainer *cu = user->FindChannel(this); + if (!this->users.erase(user)) Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant user " << user->nick << " from channel " << this->name; - return; - } - cul = *cit; - this->users.erase(cit); - ChanUserList::iterator uit, uit_end; - for (uit = user->chans.begin(), uit_end = user->chans.end(); uit != uit_end && (*uit)->chan != this; ++uit); - if (uit == uit_end) + if (!user->chans.erase(this)) Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant channel " << this->name << " from " << user->nick << "'s channel list"; - else - { - if (cul != *uit) - Log(LOG_DEBUG) << "Channel::DeleteUser() mismatch between user and channel usre container objects"; - user->chans.erase(uit); - } - delete cul; + delete cu; /* Channel is persistent, it shouldn't be deleted and the service bot should stay */ if (this->HasExt("PERSIST") || (this->ci && this->ci->HasExt("PERSIST"))) @@ -238,30 +216,30 @@ void Channel::DeleteUser(User *user) delete this; } -ChanUserContainer *Channel::FindUser(const User *u) const +ChanUserContainer *Channel::FindUser(User *u) const { - for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it) - if ((*it)->user == u) - return *it; + ChanUserList::const_iterator it = this->users.find(u); + if (it != this->users.end()) + return it->second; return NULL; } -bool Channel::HasUserStatus(const User *u, ChannelModeStatus *cms) const +bool Channel::HasUserStatus(User *u, ChannelModeStatus *cms) { /* Usually its more efficient to search the users channels than the channels users */ ChanUserContainer *cc = u->FindChannel(this); if (cc) { if (cms) - return cc->status.modes.count(cms->name); + return cc->status.HasMode(cms->mchar); else - return cc->status.modes.empty(); + return cc->status.Empty(); } return false; } -bool Channel::HasUserStatus(const User *u, const Anope::string &mname) const +bool Channel::HasUserStatus(User *u, const Anope::string &mname) { return HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(ModeManager::FindChannelModeByName(mname))); } @@ -345,7 +323,7 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anop /* Set the status on the user */ ChanUserContainer *cc = u->FindChannel(this); if (cc) - cc->status.modes.insert(cm->name); + cc->status.AddMode(cm->mchar); FOREACH_RESULT(I_OnChannelModeSet, OnChannelModeSet(this, setter, cm->name, param)); @@ -418,7 +396,7 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const A /* Remove the status on the user */ ChanUserContainer *cc = u->FindChannel(this); if (cc) - cc->status.modes.erase(cm->name); + cc->status.DelMode(cm->mchar); FOREACH_RESULT(I_OnChannelModeUnset, OnChannelModeUnset(this, setter, cm->name, param)); @@ -427,7 +405,7 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const A /* Reset modes on bots if we're supposed to */ if (this->ci && this->ci->bi && this->ci->bi == bi) { - if (ModeManager::DefaultBotModes.modes.count(cm->name)) + if (ModeManager::DefaultBotModes.HasMode(cm->mchar)) this->SetMode(bi, cm, bi->GetUID()); } @@ -964,16 +942,16 @@ void Channel::SetCorrectModes(User *user, bool give_modes, bool check_noop) if (give_modes && (!user->Account() || user->Account()->HasExt("AUTOOP")) && (!check_noop || !ci->HasExt("NOAUTOOP"))) { if (owner && u_access.HasPriv("AUTOOWNER")) - this->SetMode(NULL, "OWNER", user->GetUID()); + this->SetMode(NULL, owner, user->GetUID()); else if (admin && u_access.HasPriv("AUTOPROTECT")) - this->SetMode(NULL, "PROTECT", user->GetUID()); + this->SetMode(NULL, admin, user->GetUID()); if (op && u_access.HasPriv("AUTOOP")) - this->SetMode(NULL, "OP", user->GetUID()); + this->SetMode(NULL, op, user->GetUID()); else if (halfop && u_access.HasPriv("AUTOHALFOP")) - this->SetMode(NULL, "HALFOP", user->GetUID()); + this->SetMode(NULL, halfop, user->GetUID()); else if (voice && u_access.HasPriv("AUTOVOICE")) - this->SetMode(NULL, "VOICE", user->GetUID()); + this->SetMode(NULL, voice, user->GetUID()); } /* If this channel has secureops, or the registered channel mode exists and the channel does not have +r set (aka the channel * was created just now or while we were off), or the registered channel mode does not exist and channel is syncing (aka just @@ -983,16 +961,16 @@ void Channel::SetCorrectModes(User *user, bool give_modes, bool check_noop) if ((ci->HasExt("SECUREOPS") || (registered && !this->HasMode("REGISTERED")) || (!registered && this->HasExt("SYNCING") && user->server->IsSynced())) && !user->server->IsULined()) { if (owner && !u_access.HasPriv("AUTOOWNER") && !u_access.HasPriv("OWNERME")) - this->RemoveMode(NULL, "OWNER", user->GetUID()); + this->RemoveMode(NULL, owner, user->GetUID()); if (admin && !u_access.HasPriv("AUTOPROTECT") && !u_access.HasPriv("PROTECTME")) - this->RemoveMode(NULL, "PROTECT", user->GetUID()); + this->RemoveMode(NULL, admin, user->GetUID()); if (op && this->HasUserStatus(user, "OP") && !u_access.HasPriv("AUTOOP") && !u_access.HasPriv("OPDEOPME")) - this->RemoveMode(NULL, "OP", user->GetUID()); + this->RemoveMode(NULL, op, user->GetUID()); if (halfop && !u_access.HasPriv("AUTOHALFOP") && !u_access.HasPriv("HALFOPME")) - this->RemoveMode(NULL, "HALFOP", user->GetUID()); + this->RemoveMode(NULL, halfop, user->GetUID()); } // Check mlock @@ -1016,7 +994,7 @@ void Channel::SetCorrectModes(User *user, bool give_modes, bool check_noop) } } -bool Channel::Unban(const User *u, bool full) +bool Channel::Unban(User *u, bool full) { if (!this->HasMode("BAN")) return false; @@ -1047,3 +1025,12 @@ Channel* Channel::Find(const Anope::string &name) return NULL; } +Channel *Channel::FindOrCreate(const Anope::string &name, bool &created, time_t ts) +{ + Channel* &chan = ChannelList[name]; + created = chan == NULL; + if (!chan) + chan = new Channel(name, ts); + return chan; +} + diff --git a/src/config.cpp b/src/config.cpp index 1c2aae988..4d1267f23 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -137,6 +137,7 @@ ServerConfig::ServerConfig() Log() << "Unknown casemap " << this->CaseMap << " - casemap not changed"; } } + Anope::CaseMapRebuild(); if (this->SessionIPv4CIDR > 32 || this->SessionIPv6CIDR > 128) throw ConfigException("Session CIDR value out of range"); @@ -894,12 +895,10 @@ static bool DoServices(ServerConfig *config, const Anope::string &, const Anope: continue; // Can't happen /* Remove all existing modes */ - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - { - ChannelMode *cm = ModeManager::ChannelModes[i]; - if (cm && cm->type == MODE_STATUS) - c->RemoveMode(bi, cm, bi->GetUID()); - } + ChanUserContainer *cu = c->FindUser(bi); + if (cu != NULL) + for (size_t i = 0; i < cu->status.Modes().length(); ++i) + c->RemoveMode(bi, ModeManager::FindChannelModeByChar(cu->status.Modes()[i]), bi->GetUID()); /* Set the new modes */ for (unsigned j = 0; j < want_modes.length(); ++j) { diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 2f7816746..aac381c9b 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -13,6 +13,30 @@ /* Case map in use by Anope */ std::locale Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>()); +/* Cache of the above case map, forced upper */ +static unsigned char case_map_upper[256], case_map_lower[256]; + +/* called whenever Anope::casemap is modified to rebuild the casemap cache */ +void Anope::CaseMapRebuild() +{ + const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); + + for (unsigned i = 0; i < sizeof(case_map_upper); ++i) + { + case_map_upper[i] = ct.toupper(i); + case_map_lower[i] = ct.tolower(i); + } +} + +unsigned char Anope::tolower(unsigned char c) +{ + return case_map_lower[c]; +} + +unsigned char Anope::toupper(unsigned char c) +{ + return case_map_upper[c]; +} /* * @@ -23,29 +47,25 @@ std::locale Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<c bool ci::ci_char_traits::eq(char c1st, char c2nd) { - const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); - return ct.toupper(c1st) == ct.toupper(c2nd); + return case_map_upper[static_cast<unsigned char>(c1st)] == case_map_upper[static_cast<unsigned char>(c2nd)]; } bool ci::ci_char_traits::ne(char c1st, char c2nd) { - const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); - return ct.toupper(c1st) != ct.toupper(c2nd); + return !eq(c1st, c2nd); } bool ci::ci_char_traits::lt(char c1st, char c2nd) { - const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); - return ct.toupper(c1st) < ct.toupper(c2nd); + return case_map_upper[static_cast<unsigned char>(c1st)] < case_map_upper[static_cast<unsigned char>(c2nd)]; } int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n) { - const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); - for (unsigned i = 0; i < n; ++i) { - register char c1 = ct.toupper(*str1), c2 = ct.toupper(*str2); + register unsigned char c1 = case_map_upper[static_cast<unsigned char>(*str1)], + c2 = case_map_upper[static_cast<unsigned char>(*str2)]; if (c1 > c2) return 1; @@ -62,9 +82,7 @@ int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n) const char *ci::ci_char_traits::find(const char *s1, int n, char c) { - const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap); - register char c_u = ct.toupper(c); - while (n-- > 0 && ct.toupper(*s1) != c_u) + while (n-- > 0 && case_map_upper[static_cast<unsigned char>(*s1)] != static_cast<unsigned char>(c)) ++s1; return n >= 0 ? s1 : NULL; } @@ -74,35 +92,29 @@ bool ci::less::operator()(const Anope::string &s1, const Anope::string &s2) cons return s1.ci_str().compare(s2.ci_str()) < 0; } -sepstream::sepstream(const Anope::string &source, char seperator) : tokens(source), sep(seperator) +sepstream::sepstream(const Anope::string &source, char seperator) : tokens(source), sep(seperator), pos(0) { - last_starting_position = n = tokens.begin(); } bool sepstream::GetToken(Anope::string &token) { - Anope::string::iterator lsp = last_starting_position; + size_t p = this->pos; - while (n != tokens.end()) + while (p < this->tokens.length() && this->tokens[p] == this->sep) + ++p; + + if (this->StreamEnd()) { - if (*n == sep || n + 1 == tokens.end()) - { - last_starting_position = n + 1; - token = Anope::string(lsp, n + 1 == tokens.end() ? n + 1 : n); - - while (token.length() && token.rfind(sep) == token.length() - 1) - token.erase(token.end() - 1); - - ++n; - - return true; - } - - ++n; + token.clear(); + return false; } - token.clear(); - return false; + while (p < this->tokens.length() && this->tokens[p] != this->sep) + ++p; + + token = this->tokens.substr(this->pos, p - this->pos); + this->pos = p + 1; + return true; } bool sepstream::GetToken(Anope::string &token, int num) @@ -135,11 +147,11 @@ bool sepstream::GetTokenRemainder(Anope::string &token, int num) const Anope::string sepstream::GetRemaining() { - return Anope::string(n, tokens.end()); + return !this->StreamEnd() ? this->tokens.substr(this->pos) : ""; } bool sepstream::StreamEnd() { - return n == tokens.end(); + return this->pos >= this->tokens.length(); } diff --git a/src/logger.cpp b/src/logger.cpp index d46030486..f738cb2e1 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -56,9 +56,7 @@ static Anope::string GetTimeStamp() static inline Anope::string CreateLogName(const Anope::string &file, time_t t = Anope::CurTime) { char timestamp[32]; - tm *tm = localtime(&t); - strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm); return Anope::LogDir + "/" + file + "." + timestamp; @@ -68,7 +66,12 @@ LogFile::LogFile(const Anope::string &name) : filename(name), stream(name.c_str( { } -Anope::string LogFile::GetName() const +LogFile::~LogFile() +{ + this->stream.close(); +} + +const Anope::string &LogFile::GetName() const { return this->filename; } @@ -77,8 +80,6 @@ Log::Log(LogType t, const Anope::string &cat, const BotInfo *b) : bi(b), u(NULL) { if (!bi && Config) bi = Global; - if (bi) - this->sources.push_back(bi->nick); } Log::Log(LogType t, CommandSource &source, Command *_c, const ChannelInfo *_ci) : nick(source.GetNick()), u(source.GetUser()), nc(source.nc), c(_c), chan(NULL), ci(_ci), s(NULL), m(NULL), type(t) @@ -96,13 +97,6 @@ Log::Log(LogType t, CommandSource &source, Command *_c, const ChannelInfo *_ci) if (this->bi == NULL && Config) this->bi = Global; this->category = c->name; - if (this->bi) - this->sources.push_back(this->bi->nick); - if (u) - this->sources.push_back(u->nick); - this->sources.push_back(c->name); - if (ci) - this->sources.push_back(ci->name); } Log::Log(const User *_u, Channel *ch, const Anope::string &cat) : bi(NULL), u(_u), nc(NULL), c(NULL), chan(ch), ci(chan ? *chan->ci : NULL), s(NULL), m(NULL), type(LOG_CHANNEL), category(cat) @@ -112,11 +106,6 @@ Log::Log(const User *_u, Channel *ch, const Anope::string &cat) : bi(NULL), u(_u if (Config) this->bi = ChanServ; - if (this->bi) - this->sources.push_back(this->bi->nick); - if (u) - this->sources.push_back(u->nick); - this->sources.push_back(chan->name); } Log::Log(const User *_u, const Anope::string &cat, const BotInfo *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_USER), category(cat) @@ -126,9 +115,6 @@ Log::Log(const User *_u, const Anope::string &cat, const BotInfo *_bi) : bi(_bi) if (!this->bi && Config) this->bi = Global; - if (this->bi) - this->sources.push_back(this->bi->nick); - this->sources.push_back(u->nick); } Log::Log(Server *serv, const Anope::string &cat, const BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(serv), m(NULL), type(LOG_SERVER), category(cat) @@ -140,23 +126,16 @@ Log::Log(Server *serv, const Anope::string &cat, const BotInfo *_bi) : bi(_bi), this->bi = OperServ; if (!this->bi && Config) this->bi = Global; - if (this->bi) - this->sources.push_back(this->bi->nick); - this->sources.push_back(s->GetName()); } Log::Log(const BotInfo *b, const Anope::string &cat) : bi(b), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_NORMAL), category(cat) { if (!this->bi && Config) this->bi = Global; - if (this->bi) - this->sources.push_back(bi->nick); } Log::Log(Module *mod, const Anope::string &cat) : bi(NULL), u(NULL), nc(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), m(mod), type(LOG_MODULE), category(cat) { - if (m) - this->sources.push_back(m->name); } Log::~Log() @@ -167,11 +146,12 @@ Log::~Log() std::cout << GetTimeStamp() << " " << this->BuildPrefix() << this->buf.str() << std::endl; else if (this->type == LOG_TERMINAL) std::cout << this->BuildPrefix() << this->buf.str() << std::endl; - for (unsigned i = 0; Config && i < Config->LogInfos.size(); ++i) - { - LogInfo *l = Config->LogInfos[i]; - l->ProcessMessage(this); - } + + if (Config) + for (unsigned i = 0; i < Config->LogInfos.size(); ++i) + if (Config->LogInfos[i]->HasType(this->type, this->category)) + Config->LogInfos[i]->ProcessMessage(this); + FOREACH_MOD(I_OnLog, OnLog(this)); } @@ -264,40 +244,20 @@ Anope::string Log::BuildPrefix() const return buffer; } -LogInfo::LogInfo(int la, bool rio, bool ldebug) : log_age(la), raw_io(rio), debug(ldebug) +LogInfo::LogInfo(int la, bool rio, bool ldebug) : last_day(0), log_age(la), raw_io(rio), debug(ldebug) { } LogInfo::~LogInfo() { - for (std::map<Anope::string, LogFile *>::iterator it = this->logfiles.begin(), it_end = this->logfiles.end(); it != it_end; ++it) - { - LogFile *f = it->second; - - if (f && f->stream.is_open()) - f->stream.close(); - delete f; - } + for (unsigned i = 0; i < this->logfiles.size(); ++i) + delete this->logfiles[i]; this->logfiles.clear(); } -void LogInfo::AddType(std::list<Anope::string> &list, const Anope::string &type) -{ - for (std::list<Anope::string>::iterator it = list.begin(), it_end = list.end(); it != it_end; ++it) - { - if (Anope::Match(type, *it)) - { - Log() << "Log: Type " << type << " is already covered by " << *it; - return; - } - } - - list.push_back(type); -} - bool LogInfo::HasType(LogType ltype, const Anope::string &type) const { - const std::list<Anope::string> *list = NULL; + const std::vector<Anope::string> *list = NULL; switch (ltype) { case LOG_ADMIN: @@ -338,9 +298,9 @@ bool LogInfo::HasType(LogType ltype, const Anope::string &type) const if (list == NULL) return false; - for (std::list<Anope::string>::const_iterator it = list->begin(), it_end = list->end(); it != it_end; ++it) + for (unsigned i = 0; i < list->size(); ++i) { - Anope::string cat = *it; + Anope::string cat = list->at(i); bool inverse = false; if (cat[0] == '~') { @@ -356,36 +316,63 @@ bool LogInfo::HasType(LogType ltype, const Anope::string &type) const return false; } -void LogInfo::ProcessMessage(const Log *l) +void LogInfo::OpenLogFiles() { - static time_t lastwarn = Anope::CurTime; + for (unsigned i = 0; i < this->logfiles.size(); ++i) + delete this->logfiles[i]; + this->logfiles.clear(); - if (!l) - throw CoreException("Bad values passed to LogInfo::ProcessMessages"); - else if (!this->HasType(l->type, l->category)) - return; - + for (unsigned i = 0; i < this->targets.size(); ++i) + { + const Anope::string &target = this->targets[i]; + + if (target.empty() || target[0] == '#' || target == "globops") + continue; + + LogFile *lf = new LogFile(CreateLogName(target)); + if (!lf->stream.is_open()) + { + Log() << "Unable to open logfile " << lf->GetName(); + delete lf; + } + else + this->logfiles.push_back(lf); + } +} + +void LogInfo::ProcessMessage(const Log *l) +{ if (!this->sources.empty()) { bool log = false; - for (std::list<Anope::string>::const_iterator it = this->sources.begin(), it_end = this->sources.end(); it != it_end; ++it) + for (unsigned i = 0; i < this->sources.size() && !log; ++i) { - if (std::find(l->sources.begin(), l->sources.end(), *it) != l->sources.end()) - { + const Anope::string &src = this->sources[i]; + + if (l->bi && src == l->bi->nick) + log = true; + else if (l->u && src == l->u->nick) + log = true; + else if (l->nc && src == l->nc->display) + log = true; + else if (l->ci && src == l->ci->name) + log = true; + else if (l->m && src == l->m->name) + log = true; + else if (l->s && src == l->s->GetName()) log = true; - break; - } } if (!log) return; } - for (std::list<Anope::string>::iterator it = this->targets.begin(), it_end = this->targets.end(); it != it_end; ++it) + const Anope::string &buffer = l->BuildPrefix() + l->buf.str(); + + for (unsigned i = 0; i < this->targets.size(); ++i) { - const Anope::string &target = *it; - Anope::string buffer = l->BuildPrefix() + l->buf.str(); + const Anope::string &target = this->targets[i]; - if (target[0] == '#') + if (!target.empty() && target[0] == '#') { if (UplinkSock && l->type <= LOG_NORMAL && Me && Me->IsSynced()) { @@ -402,63 +389,35 @@ void LogInfo::ProcessMessage(const Log *l) IRCD->SendGlobops(l->bi, "%s", buffer.c_str()); } } - else - { - LogFile *log = NULL; - std::map<Anope::string, LogFile *>::iterator lit = this->logfiles.find(target); - if (lit != this->logfiles.end()) - { - log = lit->second; - if (log && log->GetName() != CreateLogName(target)) - { - delete log; - this->logfiles.erase(lit); - log = new LogFile(CreateLogName(target)); - this->logfiles[target] = log; - - if (this->log_age) - { - Anope::string oldlog = CreateLogName(target, Anope::CurTime - 86400 * this->log_age); - if (IsFile(oldlog)) - { - unlink(oldlog.c_str()); - Log(LOG_DEBUG) << "Deleted old logfile " << oldlog; - } - } - } - if (!log || !log->stream.is_open()) - { - if (log && lastwarn + 300 < Anope::CurTime) - { - lastwarn = Anope::CurTime; - Log() << "Unable to open logfile " << log->GetName(); - } - delete log; - this->logfiles.erase(lit); - log = NULL; - } - } - else if (lit == this->logfiles.end()) + } + + tm *tm = localtime(&Anope::CurTime); + if (tm->tm_mday != this->last_day) + { + this->last_day = tm->tm_mday; + this->OpenLogFiles(); + + if (this->log_age) + for (unsigned i = 0; i < this->targets.size(); ++i) { - log = new LogFile(CreateLogName(target)); + const Anope::string &target = this->targets[i]; + + if (target.empty() || target[0] == '#' || target == "globops") + continue; - if (!log->stream.is_open()) + Anope::string oldlog = CreateLogName(target, Anope::CurTime - 86400 * this->log_age); + if (IsFile(oldlog)) { - if (lastwarn + 300 < Anope::CurTime) - { - lastwarn = Anope::CurTime; - Log() << "Unable to open logfile " << log->GetName(); - } - delete log; - log = NULL; + unlink(oldlog.c_str()); + Log(LOG_DEBUG) << "Deleted old logfile " << oldlog; } - else - this->logfiles[target] = log; } + } - if (log) - log->stream << GetTimeStamp() << " " << buffer << std::endl; - } + for (unsigned i = 0; i < this->logfiles.size(); ++i) + { + LogFile *lf = this->logfiles[i]; + lf->stream << GetTimeStamp() << " " << buffer << std::endl; } } diff --git a/src/main.cpp b/src/main.cpp index 2e15f5874..059650df0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -106,6 +106,9 @@ static Anope::string GetFullProgDir(const Anope::string &argv0) int main(int ac, char **av, char **envp) { + /* String comparisons won't work until we build the case map cache, so do it first */ + Anope::CaseMapRebuild(); + BinaryDir = GetFullProgDir(av[0]); if (BinaryDir[BinaryDir.length() - 1] == '.') BinaryDir = BinaryDir.substr(0, BinaryDir.length() - 2); diff --git a/src/messages.cpp b/src/messages.cpp index 567a24b6a..178d376c3 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -64,7 +64,7 @@ void Join::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) { for (User::ChanUserList::iterator it = user->chans.begin(), it_end = user->chans.end(); it != it_end; ) { - ChanUserContainer *cc = *it++; + ChanUserContainer *cc = it->second++; Anope::string channame = cc->chan->name; FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(user, cc->chan)); @@ -84,14 +84,12 @@ void Join::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users) { - Channel *c = Channel::Find(chan); + bool created; + Channel *c = Channel::FindOrCreate(chan, created, ts ? ts : Anope::CurTime); bool keep_their_modes = true; - if (!c) - { - c = new Channel(chan, ts ? ts : Anope::CurTime); + if (created) c->Extend("SYNCING"); - } /* Some IRCds do not include a TS */ else if (!ts) ; @@ -124,7 +122,8 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co ChanUserContainer *cc = c->JoinUser(u); /* Update their status internally on the channel */ - cc->status = status; + if (keep_their_modes) + cc->status = status; /* Set whatever modes the user should have, and remove any that * they aren't allowed to have (secureops etc). @@ -193,7 +192,7 @@ void Kill::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) bi->introduced = true; for (User::ChanUserList::const_iterator cit = bi->chans.begin(), cit_end = bi->chans.end(); cit != cit_end; ++cit) - IRCD->SendJoin(bi, (*cit)->chan, &(*cit)->status); + IRCD->SendJoin(bi, cit->second->chan, &cit->second->status); } else u->KillInternal(source.GetSource(), params[1]); diff --git a/src/misc.cpp b/src/misc.cpp index ad8512c56..20a53e7cc 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -406,7 +406,7 @@ bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case } else { - if (tolower(wild) != tolower(string) && wild != '?') + if (Anope::tolower(wild) != Anope::tolower(string) && wild != '?') return false; } @@ -441,7 +441,7 @@ bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case } else { - if (tolower(wild) == tolower(string) || wild == '?') + if (Anope::tolower(wild) == Anope::tolower(string) || wild == '?') { ++m; ++s; @@ -529,7 +529,7 @@ void Anope::Unhex(const Anope::string &src, Anope::string &dest) Anope::string rv; for (size_t i = 0; i + 1 < len; i += 2) { - char h = std::tolower(src[i], Anope::casemap), l = std::tolower(src[i + 1], Anope::casemap); + char h = Anope::tolower(src[i]), l = Anope::tolower(src[i + 1]); unsigned char byte = (h >= 'a' ? h - 'a' + 10 : h - '0') << 4; byte += (l >= 'a' ? l - 'a' + 10 : l - '0'); rv += byte; diff --git a/src/modes.cpp b/src/modes.cpp index 0eee41682..a1ecdbfee 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -22,6 +22,9 @@ std::map<Channel *, StackerInfo *> ModeManager::ChannelStackerObjects; std::vector<ChannelMode *> ModeManager::ChannelModes; std::vector<UserMode *> ModeManager::UserModes; +static std::map<Anope::string, ChannelMode *> ChannelModesByName; +static std::map<Anope::string, UserMode *> UserModesByName; + /* Number of generic modes we support */ unsigned ModeManager::GenericChannelModes = 0, ModeManager::GenericUserModes = 0; @@ -32,33 +35,48 @@ std::list<Anope::string> ModeManager::ModeLockOff; /* Default modes bots have on channels */ ChannelStatus ModeManager::DefaultBotModes; -Anope::string ChannelStatus::BuildCharPrefixList() const +void ChannelStatus::AddMode(char c) { - Anope::string ret; + if (modes.find(c) == Anope::string::npos) + modes.append(c); +} - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - { - ChannelMode *cm = ModeManager::ChannelModes[i]; +void ChannelStatus::DelMode(char c) +{ + modes = modes.replace_all_cs(c, ""); +} - if (this->modes.count(cm->name)) - ret += cm->mchar; - } +bool ChannelStatus::HasMode(char c) const +{ + return modes.find(c) != Anope::string::npos; +} - return ret; +bool ChannelStatus::Empty() const +{ + return modes.empty(); +} + +void ChannelStatus::Clear() +{ + modes.clear(); +} + +const Anope::string &ChannelStatus::Modes() const +{ + return modes; } Anope::string ChannelStatus::BuildModePrefixList() const { Anope::string ret; - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) + for (size_t i = 0; i < modes.length(); ++i) { - ChannelMode *cm = ModeManager::ChannelModes[i]; - - if (this->modes.count(cm->name)) + ChannelMode *cm = ModeManager::FindChannelModeByName(modes[i]); + if (cm != NULL && cm->type == MODE_STATUS) { ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); - ret += cms->Symbol; + ret += cms->symbol; } } @@ -119,7 +137,7 @@ ChannelModeParam::~ChannelModeParam() { } -ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar, char mSymbol, short mlevel) : ChannelMode(mname, modeChar), Symbol(mSymbol), level(mlevel) +ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar, char msymbol, short mlevel) : ChannelMode(mname, modeChar), symbol(msymbol), level(mlevel) { this->type = MODE_STATUS; } @@ -296,7 +314,12 @@ bool ModeManager::AddUserMode(UserMode *um) Log() << "ModeManager: Added generic support for user mode " << um->mchar; } - ModeManager::UserModes.push_back(um); + unsigned want = um->mchar; + if (want >= ModeManager::UserModes.size()) + ModeManager::UserModes.resize(want + 1); + ModeManager::UserModes[want] = um; + + UserModesByName[um->name] = um; FOREACH_MOD(I_OnUserModeAdd, OnUserModeAdd(um)); @@ -314,7 +337,21 @@ bool ModeManager::AddChannelMode(ChannelMode *cm) Log() << "ModeManager: Added generic support for channel mode " << cm->mchar; } - ModeManager::ChannelModes.push_back(cm); + unsigned want = cm->mchar; + if (want >= ModeManager::ChannelModes.size()) + ModeManager::ChannelModes.resize(want + 1); + ModeManager::ChannelModes[want] = cm; + + if (cm->type == MODE_STATUS) + { + ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); + want = cms->symbol; + if (want >= ModeManager::ChannelModes.size()) + ModeManager::ChannelModes.resize(want + 1); + ModeManager::ChannelModes[want] = cms; + } + + ChannelModesByName[cm->name] = cm; /* Apply this mode to the new default mlock if its used */ UpdateDefaultMLock(Config); @@ -326,97 +363,111 @@ bool ModeManager::AddChannelMode(ChannelMode *cm) void ModeManager::RemoveUserMode(UserMode *um) { - for (unsigned i = 0; i < ModeManager::UserModes.size(); ++i) - { - UserMode *mode = ModeManager::UserModes[i]; - if (um == mode) - { - ModeManager::UserModes.erase(ModeManager::UserModes.begin() + i); - break; - } - } + if (!um) + return; + + unsigned want = um->mchar; + if (want >= ModeManager::UserModes.size()) + return; + + if (ModeManager::UserModes[want] != um) + return; + + ModeManager::UserModes[want] = NULL; + + UserModesByName.erase(um->name); StackerDel(um); } void ModeManager::RemoveChannelMode(ChannelMode *cm) { - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) + if (!cm) + return; + + unsigned want = cm->mchar; + if (want >= ModeManager::ChannelModes.size()) + return; + + if (ModeManager::ChannelModes[want] != cm) + return; + + ModeManager::ChannelModes[want] = NULL; + + if (cm->type == MODE_STATUS) { - ChannelMode *mode = ModeManager::ChannelModes[i]; - if (cm == mode) - { - ModeManager::ChannelModes.erase(ModeManager::ChannelModes.begin() + i); - break; - } + ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); + want = cms->symbol; + + if (want >= ModeManager::ChannelModes.size()) + return; + + if (ModeManager::ChannelModes[want] != cm) + return; + + ModeManager::ChannelModes[want] = NULL; } + ChannelModesByName.erase(cm->name); + StackerDel(cm); } -ChannelMode *ModeManager::FindChannelModeByChar(char Mode) +ChannelMode *ModeManager::FindChannelModeByChar(char mode) { - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - { - ChannelMode *cm = ModeManager::ChannelModes[i]; - if (cm->mchar == Mode) - return cm; - } - - return NULL; + unsigned want = mode; + if (want >= ModeManager::ChannelModes.size()) + return NULL; + + return ModeManager::ChannelModes[want]; } -UserMode *ModeManager::FindUserModeByChar(char Mode) +UserMode *ModeManager::FindUserModeByChar(char mode) { - for (unsigned i = 0; i < ModeManager::UserModes.size(); ++i) - { - UserMode *um = ModeManager::UserModes[i]; - if (um->mchar == Mode) - return um; - } - - return NULL; + unsigned want = mode; + if (want >= ModeManager::UserModes.size()) + return NULL; + + return ModeManager::UserModes[want]; } ChannelMode *ModeManager::FindChannelModeByName(const Anope::string &name) { - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - { - ChannelMode *cm = ModeManager::ChannelModes[i]; - if (cm->name == name) - return cm; - } - + std::map<Anope::string, ChannelMode *>::iterator it = ChannelModesByName.find(name); + if (it != ChannelModesByName.end()) + return it->second; return NULL; } UserMode *ModeManager::FindUserModeByName(const Anope::string &name) { - for (unsigned i = 0; i < ModeManager::UserModes.size(); ++i) - { - UserMode *um = ModeManager::UserModes[i]; - if (um->name == name) - return um; - } - + std::map<Anope::string, UserMode *>::iterator it = UserModesByName.find(name); + if (it != UserModesByName.end()) + return it->second; return NULL; } -char ModeManager::GetStatusChar(char Value) +char ModeManager::GetStatusChar(char value) { - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - { - ChannelMode *cm = ModeManager::ChannelModes[i]; - if (cm->type == MODE_STATUS) - { - ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); + unsigned want = value; + if (want >= ModeManager::ChannelModes.size()) + return 0; + + ChannelMode *cm = ModeManager::ChannelModes[want]; + if (cm == NULL || cm->type != MODE_STATUS) + return 0; + + return cm->mchar; +} - if (Value == cms->Symbol) - return cms->mchar; - } - } +const std::vector<ChannelMode *> &ModeManager::GetChannelModes() +{ + return ChannelModes; +} - return 0; +const std::vector<UserMode *> &ModeManager::GetUserModes() +{ + return UserModes; } void ModeManager::StackerAdd(const BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const Anope::string &Param) @@ -592,17 +643,9 @@ void ModeManager::UpdateDefaultMLock(ServerConfig *config) } /* Set Bot Modes */ - DefaultBotModes.modes.clear(); + DefaultBotModes.Clear(); for (unsigned i = 0; i < config->BotModes.length(); ++i) - { - ChannelMode *cm = ModeManager::FindChannelModeByChar(config->BotModes[i]); - - if (cm && cm->type == MODE_STATUS) - DefaultBotModes.modes.insert(cm->name); - else - /* We don't know the mode yet so just use the mode char */ - DefaultBotModes.modes.insert(config->BotModes[i]); - } + DefaultBotModes.AddMode(config->BotModes[i]); } Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0) @@ -689,7 +732,7 @@ const Anope::string Entry::GetMask() const return this->mask; } -bool Entry::Matches(const User *u, bool full) const +bool Entry::Matches(User *u, bool full) const { /* First check if this mode has defined any matches (usually for extbans). */ if (IRCD->IsExtbanValid(this->mask)) diff --git a/src/process.cpp b/src/process.cpp index 795c7c40a..a767b87c2 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -21,30 +21,21 @@ void Anope::Process(const Anope::string &buffer) /* If debugging, log the buffer */ Log(LOG_RAWIO) << "Received: " << buffer; - /* Strip all extra spaces */ - Anope::string buf = buffer; - while (buf.find(" ") != Anope::string::npos) - buf = buf.replace_all_cs(" ", " "); - - if (buf.empty()) + if (buffer.empty()) return; + spacesepstream buf_sep(buffer); + Anope::string source; - if (buf[0] == ':') + if (buffer[0] == ':') { - size_t space = buf.find_first_of(" "); - if (space == Anope::string::npos) - return; - source = buf.substr(1, space - 1); - buf = buf.substr(space + 1); - if (source.empty() || buf.empty()) - return; + buf_sep.GetToken(source); + source.erase(0, 1); } - spacesepstream buf_sep(buf); - - Anope::string command = buf; - buf_sep.GetToken(command); + Anope::string command; + if (!buf_sep.GetToken(command)) + return; Anope::string buf_token; std::vector<Anope::string> params; @@ -95,7 +86,7 @@ void Anope::Process(const Anope::string &buffer) else if (m->HasFlag(IRCDMESSAGE_REQUIRE_USER) && !src.GetUser()) Log(LOG_DEBUG) << "unexpected non-user source " << source << " for " << command; else if (m->HasFlag(IRCDMESSAGE_REQUIRE_SERVER) && !source.empty() && !src.GetServer()) - Log(LOG_DEBUG) << "unexpected non-server soruce " << source << " for " << command; + Log(LOG_DEBUG) << "unexpected non-server source " << source << " for " << command; else m->Run(src, params); } diff --git a/src/protocol.cpp b/src/protocol.cpp index 35f302ba8..b97f1158e 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -393,7 +393,7 @@ unsigned IRCDProto::GetMaxListFor(Channel *c) MessageSource::MessageSource(const Anope::string &src) : source(src), u(NULL), s(NULL) { if (src.empty()) - this->s = !Me->GetLinks().empty() ? Me->GetLinks().front() : NULL; + this->s = Servers::GetUplink(); else if (IRCD->RequiresID || src.find('.') != Anope::string::npos) this->s = Server::Find(src); if (this->s == NULL) diff --git a/src/regchannel.cpp b/src/regchannel.cpp index a35fa5d4d..9148d99fd 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -578,7 +578,10 @@ void ChannelInfo::AddAccess(ChanAccess *taccess) const NickAlias *na = NickAlias::Find(taccess->mask); if (na != NULL) + { na->nc->AddChannelReference(this); + taccess->nc = na->nc; + } } ChanAccess *ChannelInfo::GetAccess(unsigned index) const @@ -612,8 +615,19 @@ AccessGroup ChannelInfo::AccessFor(const User *u) group.nc = nc; for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i) - if (this->GetAccess(i)->Matches(u, nc)) - group.push_back(this->GetAccess(i)); + { + ChanAccess *a = this->GetAccess(i); + + if (a->nc) + { + if (a->nc == nc) + group.push_back(a); + } + else if (a->Matches(u, nc)) + { + group.push_back(a); + } + } if (group.founder || !group.empty()) { @@ -635,8 +649,19 @@ AccessGroup ChannelInfo::AccessFor(const NickCore *nc) group.nc = nc; for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i) - if (this->GetAccess(i)->Matches(NULL, nc)) + { + ChanAccess *a = this->GetAccess(i); + + if (a->nc) + { + if (a->nc == nc) + group.push_back(a); + } + else if (this->GetAccess(i)->Matches(NULL, nc)) + { group.push_back(this->GetAccess(i)); + } + } if (group.founder || !group.empty()) { diff --git a/src/servers.cpp b/src/servers.cpp index 1dd9d8a37..28ff7bf17 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -23,6 +23,9 @@ /* Anope */ Server *Me = NULL; +Anope::map<Server *> Servers::ByName; +Anope::map<Server *> Servers::ByID; + std::set<Anope::string> Servers::Capab; Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Anope::string &desc, const Anope::string &ssid, bool jupe) : name(sname), hops(shops), description(desc), sid(ssid), uplink(up) @@ -30,6 +33,10 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano syncing = true; juped = jupe; + Servers::ByName[sname] = this; + if (!ssid.empty()) + Servers::ByID[ssid] = this; + Log(this, "connect") << "uplinked to " << (this->uplink ? this->uplink->GetName() : "no uplink") << " connected to the network"; /* Add this server to our uplinks leaf list */ @@ -105,8 +112,8 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano if (c->users.empty()) IRCD->SendChannel(c); else - for (User::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit) - IRCD->SendJoin((*cit)->user, c, &(*cit)->status); + for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit) + IRCD->SendJoin(cit->second->user, c, &cit->second->status); } } } @@ -148,6 +155,10 @@ Server::~Server() for (unsigned i = this->links.size(); i > 0; --i) this->links[i - 1]->Delete(this->quit_reason); + + Servers::ByName.erase(this->name); + if (!this->sid.empty()) + Servers::ByID.erase(this->sid); } void Server::Delete(const Anope::string &reason) @@ -248,12 +259,8 @@ void Server::Sync(bool sync_links) ChannelInfo *ci = it->second; if (ci->HasExt("PERSIST")) { - bool created = false; - if (!ci->c) - { - ci->c = new Channel(ci->name, ci->time_registered); - created = true; - } + bool created; + ci->c = Channel::FindOrCreate(ci->name, created, ci->time_registered); if (ModeManager::FindChannelModeByName("PERM") != NULL) { ci->c->SetMode(NULL, "PERM"); @@ -325,30 +332,21 @@ void Server::Notice(const BotInfo *source, const Anope::string &message) IRCD->SendGlobalNotice(source, this, message); } -Server *Server::Find(const Anope::string &name, Server *s) +Server *Server::Find(const Anope::string &name, bool name_only) { - Log(LOG_DEBUG_2) << "Server::Find called for " << name; - - if (!s) - s = Me; - if (s->GetName().equals_ci(name) || s->GetSID().equals_cs(name)) - return s; - - if (!s->GetLinks().empty()) + Anope::map<Server *>::iterator it; + + if (!name_only) { - for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i) - { - Server *serv = s->GetLinks()[i]; - - if (serv->GetName().equals_ci(name) || serv->GetSID().equals_cs(name)) - return serv; - Log(LOG_DEBUG_2) << "Server::Find checking " << serv->GetName() << " server tree for " << name; - Server *server = Server::Find(name, serv); - if (server) - return server; - } + it = Servers::ByID.find(name); + if (it != Servers::ByID.end()) + return it->second; } - + + it = Servers::ByName.find(name); + if (it != Servers::ByName.end()) + return it->second; + return NULL; } diff --git a/src/users.cpp b/src/users.cpp index 708a8062c..1355911bf 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -66,7 +66,7 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope: this->nc = NULL; this->UpdateHost(); - if (sserver) // Our bots are introduced on startup with no server + if (sserver && sserver->IsSynced()) // Our bots are introduced on startup with no server { ++sserver->users; Log(this, "connect") << (!svhost.empty() ? Anope::string("(") + svhost + ") " : "") << "(" << srealname << ") " << sip << " connected to the network (" << sserver->GetName() << ")"; @@ -76,7 +76,8 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope: { MaxUserCount = UserListByNick.size(); MaxUserTime = Anope::CurTime; - Log(this, "maxusers") << "connected - new maximum user count: " << UserListByNick.size(); + if (sserver && sserver->IsSynced()) + Log(this, "maxusers") << "connected - new maximum user count: " << UserListByNick.size(); } bool exempt = false; @@ -230,7 +231,8 @@ User::~User() { if (this->server != NULL) { - Log(this, "disconnect") << "(" << this->realname << ") disconnected from the network (" << this->server->GetName() << ")"; + if (this->server->IsSynced()) + Log(this, "disconnect") << "(" << this->realname << ") disconnected from the network (" << this->server->GetName() << ")"; --this->server->users; } @@ -243,7 +245,7 @@ User::~User() --OperCount; while (!this->chans.empty()) - this->chans.front()->chan->DeleteUser(this); + this->chans.begin()->second->chan->DeleteUser(this); UserListByNick.erase(this->nick); if (!this->uid.empty()) @@ -422,6 +424,9 @@ void User::Identify(NickAlias *na) void User::Login(NickCore *core) { + if (core == this->nc) + return; + this->Logout(); this->nc = core; core->users.push_back(this); @@ -648,7 +653,8 @@ void User::SetModesInternal(const char *umodes, ...) vsnprintf(buf, BUFSIZE - 1, umodes, args); va_end(args); - Log(this, "mode") << "changes modes to " << buf; + if (this->server && this->server->IsSynced()) + Log(this, "mode") << "changes modes to " << buf; spacesepstream sep(buf); sep.GetToken(modebuf); @@ -718,11 +724,11 @@ Anope::string User::GetModes() const return m + params; } -ChanUserContainer *User::FindChannel(const Channel *c) const +ChanUserContainer *User::FindChannel(Channel *c) const { - for (User::ChanUserList::const_iterator it = this->chans.begin(), it_end = this->chans.end(); it != it_end; ++it) - if ((*it)->chan == c) - return *it; + User::ChanUserList::const_iterator it = this->chans.find(c); + if (it != this->chans.end()) + return it->second; return NULL; } |