]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Change User::oper to an OperInfo reference
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Wed, 21 Oct 2009 23:45:44 +0000 (23:45 +0000)
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Wed, 21 Oct 2009 23:45:44 +0000 (23:45 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11945 e03df62e-2008-0410-955e-edbf42e46eb7

20 files changed:
include/configreader.h
include/users.h
src/command_parse.cpp
src/commands/cmd_oper.cpp
src/configreader.cpp
src/mode.cpp
src/modes/umode_o.cpp
src/modules/m_check.cpp
src/modules/m_httpd_stats.cpp
src/modules/m_operchans.cpp
src/modules/m_operjoin.cpp
src/modules/m_operlevels.cpp
src/modules/m_opermodes.cpp
src/modules/m_override.cpp
src/modules/m_spanningtree/netburst.cpp
src/modules/m_spanningtree/opertype.cpp
src/modules/m_sqloper.cpp
src/modules/m_swhois.cpp
src/users.cpp
src/whois.cpp

index 3ec4ca826c49513e650a042148f51afa94211365..d4bc4b71bef2a0c2df7f3b3707889ef88738aed8 100644 (file)
@@ -61,8 +61,6 @@ struct CoreExport ConfigTag : public refcountbase
  */
 typedef std::multimap<std::string, reference<ConfigTag> > ConfigDataHash;
 
-typedef std::map<std::string, reference<ConfigTag> > TagIndex;
-
 /** Defines the server's length limits on various length-limited
  * items such as topics, nicknames, channel names etc.
  */
@@ -112,6 +110,30 @@ class ServerLimits
        }
 };
 
+class CoreExport OperInfo : public refcountbase
+{
+ public:
+       /** <oper> block used for this oper-up. May be NULL. */
+       reference<ConfigTag> oper_block;
+       /** <type> block used for this oper-up. Valid for local users, may be NULL on remote */
+       reference<ConfigTag> type_block;
+       /** <class> blocks referenced from the <type> block. These define individual permissions */
+       std::vector<reference<ConfigTag> > class_blocks;
+       /** Name of the oper type; i.e. the one shown in WHOIS */
+       std::string name;
+
+       /** Get a configuration item, searching in the oper, type, and class blocks (in that order) */
+       std::string getConfig(const std::string& key);
+
+       inline const char* NameStr()
+       {
+               return irc::Spacify(name.c_str());
+       }
+};
+
+typedef std::map<std::string, reference<ConfigTag> > TagIndex;
+typedef std::map<std::string, reference<OperInfo> > OperIndex;
+
 /** This class holds the bulk of the runtime configuration for the ircd.
  * It allows for reading new config values, accessing configuration files,
  * and storage of the configuration data needed to run the ircd, such as
@@ -495,13 +517,10 @@ class CoreExport ServerConfig
         */
        bool FullHostInTopic;
 
-       /** All oper type definitions from the config file
-        */
-       TagIndex opertypes;
-
-       /** All oper class definitions from the config file
+       /** Oper block and type index.
+        * For anonymous oper blocks (type only), prefix with a space.
         */
-       TagIndex operclass;
+       OperIndex oper_blocks;
 
        /** Saved argv from startup
         */
index 51600e3af8f1eb1aae86d5a35cb4a285f96bfe7c..bb8fba00746fc1dd47e187cc41668e101e318e7b 100644 (file)
@@ -60,6 +60,7 @@ enum RegistrationState {
 class Channel;
 class UserResolver;
 struct ConfigTag;
+class OperInfo;
 
 /** Holds information relevent to &lt;connect allow&gt; and &lt;connect deny&gt; tags in the config file.
  */
@@ -348,11 +349,8 @@ class CoreExport User : public StreamSocket
        time_t awaytime;
 
        /** The oper type they logged in as, if they are an oper.
-        * This is used to check permissions in operclasses, so that
-        * we can say 'yea' or 'nay' to any commands they issue.
-        * The value of this was the value of a valid 'type name=' tag
         */
-       std::string oper;
+       reference<OperInfo> oper;
 
        /** Used by User to indicate the registration status of the connection
         * It is a bitfield of the REG_NICK, REG_USER and REG_ALL bits to indicate
@@ -530,9 +528,8 @@ class CoreExport User : public StreamSocket
 
        /** Oper up the user using the given opertype.
         * This will also give the +o usermode.
-        * @param opertype The oper type to oper as
         */
-       void Oper(const std::string &opertype, const std::string &opername);
+       void Oper(OperInfo* info);
 
        /** Change this users hash key to a new string.
         * You should not call this function directly. It is used by the core
@@ -949,7 +946,7 @@ inline FakeUser* IS_SERVER(User* u)
        return u->GetFd() == FD_FAKEUSER_NUMBER ? static_cast<FakeUser*>(u) : NULL;
 }
 /** Is an oper */
-#define IS_OPER(x) (!x->oper.empty())
+#define IS_OPER(x) (x->oper)
 /** Is away */
 #define IS_AWAY(x) (!x->awaymsg.empty())
 
index 9fc8f85bb449999643d1d90b1f7d5e6cbbad44c4..8835070580feb05c6bc21f8959cbd3a425b01193 100644 (file)
@@ -340,7 +340,8 @@ bool CommandParser::ProcessCommand(User *user, std::string &cmd)
                }
                if (!user->HasPermission(command))
                {
-                       user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to command %s",user->nick.c_str(),irc::Spacify(user->oper.c_str()),command.c_str());
+                       user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to command %s",
+                               user->nick.c_str(), user->oper->NameStr(), command.c_str());
                        return do_more;
                }
        }
index 428e7b1095609508f559cac25584b516c9c8c4ed..b2db8c95cfab54dcb9574db16ef0d2aca3f07178 100644 (file)
@@ -54,8 +54,6 @@ CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, L
 {
        char TheHost[MAXBUF];
        char TheIP[MAXBUF];
-       std::string type;
-       bool found = false;
        bool match_login = false;
        bool match_pass = false;
        bool match_hosts = false;
@@ -63,89 +61,51 @@ CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, L
        snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(),user->host.c_str());
        snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString());
 
-       for (int i = 0;; i++)
+       OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]);
+       if (i != ServerInstance->Config->oper_blocks.end())
        {
-               ConfigTag* tag = ServerInstance->Config->ConfValue("oper", i);
-               if (!tag)
-                       break;
-               if (tag->getString("name") != parameters[0])
-                       continue;
+               OperInfo* ifo = i->second;
+               ConfigTag* tag = ifo->oper_block;
                match_login = true;
                match_pass = !ServerInstance->PassCompare(user, tag->getString("password"), parameters[1], tag->getString("hash"));
                match_hosts = OneOfMatches(TheHost,TheIP,tag->getString("host"));
 
                if (match_pass && match_hosts)
                {
-                       type = tag->getString("type");
-                       ConfigTag* typeTag = ServerInstance->Config->opertypes[type];
-
-                       if (typeTag)
+                       /* found this oper's opertype */
+                       std::string host = ifo->getConfig("host");
+                       if (!host.empty())
+                               user->ChangeDisplayedHost(host.c_str());
+                       std::string opClass = ifo->getConfig("class");
+                       if (!opClass.empty())
                        {
-                               /* found this oper's opertype */
-                               if (!ServerInstance->IsNick(type.c_str(), ServerInstance->Config->Limits.NickMax))
-                               {
-                                       user->WriteNumeric(491, "%s :Invalid oper type (oper types must follow the same syntax as nicknames)",user->nick.c_str());
-                                       ServerInstance->SNO->WriteToSnoMask('o',"CONFIGURATION ERROR! Oper type '%s' contains invalid characters",type.c_str());
-                                       ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but oper type erroneous.", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
-                                       return CMD_FAILURE;
-                               }
-                               std::string host = typeTag->getString("host");
-                               if (!host.empty())
-                                       user->ChangeDisplayedHost(host.c_str());
-                               std::string opClass = typeTag->getString("class");
-                               if (!opClass.empty())
-                               {
-                                       user->SetClass(opClass);
-                                       user->CheckClass();
-                               }
-                               found = true;
+                               user->SetClass(opClass);
+                               user->CheckClass();
                        }
-               }
-               break;
-       }
-       if (found)
-       {
-               /* correct oper credentials */
-               user->Oper(type, parameters[0]);
-       }
-       else
-       {
-               char broadcast[MAXBUF];
-
-               if (type.empty())
-               {
-                       std::string fields;
-                       if (!match_login)
-                               fields.append("login ");
-                       if (!match_pass)
-                               fields.append("password ");
-                       if (!match_hosts)
-                               fields.append("hosts");
-
-                       // tell them they suck, and lag them up to help prevent brute-force attacks
-                       user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str());
-                       user->Penalty += 10;
-
-                       snprintf(broadcast, MAXBUF, "WARNING! Failed oper attempt by %s!%s@%s using login '%s': The following fields do not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
-                       ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
-                       ServerInstance->PI->SendSNONotice("o", std::string("OPER: ") + broadcast);
-
-                       ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': The following fields did not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
-                       return CMD_FAILURE;
-               }
-               else
-               {
-                       user->WriteNumeric(491, "%s :Your oper block does not have a valid opertype associated with it",user->nick.c_str());
-
-                       snprintf(broadcast, MAXBUF, "CONFIGURATION ERROR! Oper block '%s': missing OperType %s",parameters[0].c_str(),type.c_str());
-
-                       ServerInstance->SNO->WriteToSnoMask('o', std::string(broadcast));
-
-                       ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': credentials valid, but oper type nonexistent.", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str());
-                       return CMD_FAILURE;
+                       user->Oper(ifo);
+                       return CMD_SUCCESS;
                }
        }
-       return CMD_SUCCESS;
+       char broadcast[MAXBUF];
+
+       std::string fields;
+       if (!match_login)
+               fields.append("login ");
+       if (!match_pass)
+               fields.append("password ");
+       if (!match_hosts)
+               fields.append("hosts");
+
+       // tell them they suck, and lag them up to help prevent brute-force attacks
+       user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str());
+       user->Penalty += 10;
+
+       snprintf(broadcast, MAXBUF, "WARNING! Failed oper attempt by %s!%s@%s using login '%s': The following fields do not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
+       ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
+       ServerInstance->PI->SendSNONotice("o", std::string("OPER: ") + broadcast);
+
+       ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': The following fields did not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
+       return CMD_FAILURE;
 }
 
 COMMAND_INIT(CommandOper)
index 6932e960ee706eeac38453462d30b750c0ce9713..5d47e1931ad9a3d77181d67c63cc1af969813be3 100644 (file)
@@ -589,8 +589,10 @@ static void ReadXLine(ServerConfig* conf, const std::string& tag, const std::str
        }
 }
 
+typedef std::map<std::string, ConfigTag*> LocalIndex;
 void ServerConfig::CrossCheckOperClassType()
 {
+       LocalIndex operclass;
        for (int i = 0;; ++i)
        {
                ConfigTag* tag = ConfValue("class", i);
@@ -610,16 +612,49 @@ void ServerConfig::CrossCheckOperClassType()
                std::string name = tag->getString("name");
                if (name.empty())
                        throw CoreException("<type:name> is missing from tag at " + tag->getTagLocation());
-               opertypes[name] = tag;
+
+               if (!ServerInstance->IsNick(name.c_str(), Limits.NickMax))
+                       throw CoreException("<type:name> is invalid (value '" + name + "')");
+
+               OperInfo* ifo = new OperInfo;
+               oper_blocks[" " + name] = ifo;
+               ifo->type_block = tag;
 
                std::string classname;
                irc::spacesepstream str(tag->getString("classes"));
                while (str.GetToken(classname))
                {
-                       if (operclass.find(classname) == operclass.end())
+                       LocalIndex::iterator cls = operclass.find(classname);
+                       if (cls == operclass.end())
                                throw CoreException("Oper type " + name + " has missing class " + classname);
+                       ifo->class_blocks.push_back(cls->second);
                }
        }
+
+       for (int i = 0;; ++i)
+       {
+               ConfigTag* tag = ConfValue("oper", i);
+               if (!tag)
+                       break;
+
+               std::string name = tag->getString("name");
+               if (name.empty())
+                       throw CoreException("<oper:name> missing from tag at " + tag->getTagLocation());
+
+               std::string type = tag->getString("type");
+               OperIndex::iterator tblk = oper_blocks.find(" " + type);
+               if (tblk == oper_blocks.end())
+                       throw CoreException("Oper block " + name + " has missing type " + type);
+               if (oper_blocks.find(name) != oper_blocks.end())
+                       throw CoreException("Duplicate oper block with name " + name);
+
+               OperInfo* ifo = new OperInfo;
+               ifo->name = type;
+               ifo->oper_block = tag;
+               ifo->type_block = tblk->second->type_block;
+               ifo->class_blocks.assign(tblk->second->class_blocks.begin(), tblk->second->class_blocks.end());
+               oper_blocks[name] = ifo;
+       }
 }
 
 void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
@@ -1255,6 +1290,16 @@ std::string ConfigTag::getTagLocation()
        return src_name + ":" + ConvToStr(src_line);
 }
 
+std::string OperInfo::getConfig(const std::string& key)
+{
+       std::string rv;
+       if (type_block)
+               type_block->readString(key, rv);
+       if (oper_block)
+               oper_block->readString(key, rv);
+       return rv;
+}
+
 /** Read the contents of a file located by `fname' into a file_cache pointed at by `F'.
  */
 bool ServerConfig::ReadFile(file_cache &F, const std::string& fname)
index c8ab6cc6276ca7698cc7ff463569094cabd9622e..d19647caea8fed728aecf7c0c43eb142d05182d8 100644 (file)
@@ -336,7 +336,7 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool
                if (IS_OPER(user))
                {
                        user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c",
-                                       user->nick.c_str(), irc::Spacify(user->oper.c_str()), type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
+                                       user->nick.c_str(), user->oper->NameStr(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
                }
                else
                {
index d5014fc685fa0147757500db467a6e6af2b8a4a2..1f8d7795018a0e3c78e774faa5e192ee5b28941d 100644 (file)
@@ -25,7 +25,7 @@ ModeUserOperator::ModeUserOperator() : ModeHandler(NULL, "oper", 'o', PARAM_NONE
 ModeAction ModeUserOperator::OnModeChange(User* source, User* dest, Channel*, std::string&, bool adding)
 {
        /* Only opers can execute this class at all */
-       if (!ServerInstance->ULine(source->nick.c_str()) && !ServerInstance->ULine(source->server) && source->oper.empty())
+       if (!ServerInstance->ULine(source->nick.c_str()) && !ServerInstance->ULine(source->server) && !IS_OPER(source))
                return MODEACTION_DENY;
 
        /* Not even opers can GIVE the +o mode, only take it away */
index 51fee9fe5a3443df5309e562ceea1b55727ffc77..158b0c5331f2e8c59d72f0ccfa1650b420bffdd5 100644 (file)
@@ -98,7 +98,7 @@ class CommandCheck : public Command
                        if (IS_OPER(targuser))
                        {
                                /* user is an oper of type ____ */
-                               user->SendText(checkstr + " opertype " + irc::Spacify(targuser->oper.c_str()));
+                               user->SendText(checkstr + " opertype " + targuser->oper->NameStr());
                        }
 
                        LocalUser* loctarg = IS_LOCAL(targuser);
index 3339a9ca83a73027de9f653ac43d58cbc99ee143..8899a363ec6760d60ad13725b00b7a28e55a3b56 100644 (file)
@@ -167,7 +167,7 @@ class ModuleHttpStats : public Module
                                        if (IS_AWAY(u))
                                                data << "<away>" << Sanitize(u->awaymsg) << "</away><awaytime>" << u->awaytime << "</awaytime>";
                                        if (IS_OPER(u))
-                                               data << "<opertype>" << Sanitize(u->oper) << "</opertype>";
+                                               data << "<opertype>" << Sanitize(u->oper->NameStr()) << "</opertype>";
                                        data << "<modes>" << u->FormatModes() << "</modes><ident>" << Sanitize(u->ident) << "</ident>";
                                        LocalUser* lu = IS_LOCAL(u);
                                        if (lu)
index 4f73e096984fcfb6108edfe66af66e97aae44f74..205d9a412b3427633d63d3e4ba0100762dec354e 100644 (file)
@@ -71,7 +71,7 @@ class ModuleOperChans : public Module
        {
                if (mask[0] == 'O' && mask[1] == ':')
                {
-                       if (IS_OPER(user) && InspIRCd::Match(user->oper, mask.substr(2)))
+                       if (IS_OPER(user) && InspIRCd::Match(user->oper->name, mask.substr(2)))
                                return MOD_RES_DENY;
                }
                return MOD_RES_PASSTHRU;
index 42b30f6fb1f7740a80ebccdad17d1ff5fd6fe82c..469bb6a2c0765770fec190dd65f2431efefb1a8a 100644 (file)
@@ -92,7 +92,7 @@ class ModuleOperjoin : public Module
                                if (ServerInstance->IsChannel(it->c_str(), ServerInstance->Config->Limits.ChanMax))
                                        Channel::JoinUser(user, it->c_str(), override, "", false, ServerInstance->Time());
 
-                       std::map<std::string, std::vector<std::string> >::iterator i = operTypeChans.find(user->oper);
+                       std::map<std::string, std::vector<std::string> >::iterator i = operTypeChans.find(user->oper->name);
 
                        if (i != operTypeChans.end())
                        {
index 7a18991c1afc48cb7da54bb1a05120b3fb68622e..6aaa2f48e579418ea0280bfc08e707d1322a0e6a 100644 (file)
@@ -42,16 +42,8 @@ class ModuleOperLevels : public Module
                        // oper killing an oper?
                        if (IS_OPER(dest) && IS_OPER(source))
                        {
-                               TagIndex::iterator dest_type = ServerInstance->Config->opertypes.find(dest->oper);
-                               TagIndex::iterator src_type = ServerInstance->Config->opertypes.find(source->oper);
-
-                               if (dest_type == ServerInstance->Config->opertypes.end())
-                                       return MOD_RES_PASSTHRU;
-                               if (src_type == ServerInstance->Config->opertypes.end())
-                                       return MOD_RES_PASSTHRU;
-
-                               long dest_level = dest_type->second->getInt("level");
-                               long source_level = src_type->second->getInt("level");
+                               long dest_level = atol(dest->oper->getConfig("level").c_str());
+                               long source_level = atol(source->oper->getConfig("level").c_str());
                                if (dest_level > source_level)
                                {
                                        if (IS_LOCAL(source)) ServerInstance->SNO->WriteGlobalSno('a', "Oper %s (level %ld) attempted to /kill a higher oper: %s (level %ld): Reason: %s",source->nick.c_str(),source_level,dest->nick.c_str(),dest_level,reason.c_str());
index 9db0b5b4ad64feb5e6dce64973f7abb0d70fada9..6b5ca10f95de62d70a3c0425dd1b8b6a8a86b05a 100644 (file)
@@ -40,13 +40,10 @@ class ModuleModesOnOper : public Module
 
        virtual void OnPostOper(User* user, const std::string &opertype, const std::string &opername)
        {
-               TagIndex::iterator typetag = ServerInstance->Config->opertypes.find(opertype);
-               if (typetag == ServerInstance->Config->opertypes.end())
-                       return;
                // whenever a user opers, go through the oper types, find their <type:modes>,
                // and if they have one apply their modes. The mode string can contain +modes
                // to add modes to the user or -modes to take modes from the user.
-               std::string ThisOpersModes = typetag->second->getString("modes");
+               std::string ThisOpersModes = user->oper->getConfig("modes");
                if (!ThisOpersModes.empty())
                {
                        ApplyModes(user, ThisOpersModes);
index 8a3fcdd62faa6509fa411edf8df949abcacee717..cf18495b56e4e65a956839fe5e748e69d61c62e2 100644 (file)
@@ -61,7 +61,7 @@ class ModuleOverride : public Module
        bool CanOverride(User* source, const char* token)
        {
                // checks to see if the oper's type has <type:override>
-               override_t::iterator j = overrides.find(source->oper);
+               override_t::iterator j = overrides.find(source->oper->name);
 
                if (j != overrides.end())
                {
index 5f47c690b19a0d52d8bd07a182750c206fac3ef3..82b6c2b685e1268f83ce68af8c09ee8f727a882c 100644 (file)
@@ -259,7 +259,7 @@ void TreeSocket::SendUsers(TreeServer* Current)
                                this->WriteLine(data);
                                if (IS_OPER(u->second))
                                {
-                                       snprintf(data,MAXBUF,":%s OPERTYPE %s", u->second->uuid.c_str(), u->second->oper.c_str());
+                                       snprintf(data,MAXBUF,":%s OPERTYPE %s", u->second->uuid.c_str(), u->second->oper->name.c_str());
                                        this->WriteLine(data);
                                }
                                if (IS_AWAY(u->second))
index dc9c0064f0197a09fc82d96395455263ef0b1a29..32ffa4fc7706d44251b0ef60cf44854d7983f179 100644 (file)
@@ -35,7 +35,14 @@ bool TreeSocket::OperType(const std::string &prefix, parameterlist &params)
                if (!IS_OPER(u))
                        ServerInstance->Users->all_opers.push_back(u);
                u->modes[UM_OPERATOR] = 1;
-               u->oper.assign(opertype, 0, 512);
+               OperIndex::iterator iter = ServerInstance->Config->oper_blocks.find(" " + opertype);
+               if (iter != ServerInstance->Config->oper_blocks.end())
+                       u->oper = iter->second;
+               else
+               {
+                       u->oper = new OperInfo;
+                       u->oper->name = opertype;
+               }
                Utils->DoOneToAllButSender(u->uuid, "OPERTYPE", params, u->server);
 
                TreeServer* remoteserver = Utils->FindServer(u->server);
index c4eaa6911000cc14187b490b2e2d3caa6a514e32..a6da1ddaafa7b30069f8921355bdfbe46841df16 100644 (file)
@@ -275,26 +275,21 @@ public:
 
        bool OperUser(User* user, const std::string &pattern, const std::string &type)
        {
-               ConfigReader Conf;
-
-               for (int j = 0; j < Conf.Enumerate("type"); j++)
-               {
-                       std::string tname = Conf.ReadValue("type","name",j);
-                       std::string hostname(user->ident);
+               OperIndex::iterator iter = ServerInstance->Config->oper_blocks.find(" " + type);
+               if (iter == ServerInstance->Config->oper_blocks.end())
+                       return false;
+               OperInfo* ifo = iter->second;
 
-                       hostname.append("@").append(user->host);
+               std::string hostname(user->ident);
 
-                       if ((tname == type) && OneOfMatches(hostname.c_str(), user->GetIPString(), pattern.c_str()))
-                       {
-                               /* Opertype and host match, looks like this is it. */
-                               std::string operhost = Conf.ReadValue("type", "host", j);
+               hostname.append("@").append(user->host);
 
-                               if (operhost.size())
-                                       user->ChangeDisplayedHost(operhost.c_str());
+               if (OneOfMatches(hostname.c_str(), user->GetIPString(), pattern.c_str()))
+               {
+                       /* Opertype and host match, looks like this is it. */
 
-                               user->Oper(type, tname);
-                               return true;
-                       }
+                       user->Oper(ifo);
+                       return true;
                }
 
                return false;
index 8949c21ef4b97f499492e4c5855d89c22a6cf412..4c262c9caa6ce92a795bd62ad42c03f739659587 100644 (file)
@@ -106,32 +106,7 @@ class ModuleSWhois : public Module
                        return;
                ConfigReader Conf;
 
-               std::string swhois;
-
-               for (int i = 0; i < Conf.Enumerate("oper"); i++)
-               {
-                       std::string name = Conf.ReadValue("oper", "name", i);
-
-                       if (name == params[0])
-                       {
-                               swhois = Conf.ReadValue("oper", "swhois", i);
-                               break;
-                       }
-               }
-
-               if (!swhois.length())
-               {
-                       for (int i = 0; i < Conf.Enumerate("type"); i++)
-                       {
-                               std::string type = Conf.ReadValue("type", "name", i);
-
-                               if (type == user->oper)
-                               {
-                                       swhois = Conf.ReadValue("type", "swhois", i);
-                                       break;
-                               }
-                       }
-               }
+               std::string swhois = user->oper->getConfig("swhois");
 
                if (!swhois.length())
                        return;
index bcf50a1fff23e5ed9fc7026d8934f584fa50f4a7..0f760e27c872cc0f39aa610338c150290d347131 100644 (file)
@@ -499,7 +499,7 @@ bool LocalUser::HasPrivPermission(const std::string &privstr, bool noisy)
        }
 
        if (noisy)
-               this->WriteServ("NOTICE %s :Oper type %s does not have access to priv %s", this->nick.c_str(), this->oper.c_str(), privstr.c_str());
+               this->WriteServ("NOTICE %s :Oper type %s does not have access to priv %s", this->nick.c_str(), oper->NameStr(), privstr.c_str());
        return false;
 }
 
@@ -637,97 +637,87 @@ CullResult LocalUser::cull()
        return User::cull();
 }
 
-void User::Oper(const std::string &opertype, const std::string &opername)
+void User::Oper(OperInfo* info)
 {
        if (this->IsModeSet('o'))
                this->UnOper();
 
        this->modes[UM_OPERATOR] = 1;
+       this->oper = info;
        this->WriteServ("MODE %s :+o", this->nick.c_str());
-       FOREACH_MOD(I_OnOper, OnOper(this, opertype));
+       FOREACH_MOD(I_OnOper, OnOper(this, info->name));
 
-       ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')", this->nick.c_str(), this->ident.c_str(), this->host.c_str(), irc::Spacify(opertype.c_str()), opername.c_str());
-       this->WriteNumeric(381, "%s :You are now %s %s", this->nick.c_str(), strchr("aeiouAEIOU", *opertype.c_str()) ? "an" : "a", irc::Spacify(opertype.c_str()));
+       std::string opername;
+       if (info->oper_block)
+               opername = info->oper_block->getString("name");
 
-       ServerInstance->Logs->Log("OPER", DEFAULT, "%s!%s@%s opered as type: %s", this->nick.c_str(), this->ident.c_str(), this->host.c_str(), opertype.c_str());
-       this->oper.assign(opertype, 0, 512);
+       ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')",
+               nick.c_str(), ident.c_str(), host.c_str(), info->NameStr(), opername.c_str());
+       this->WriteNumeric(381, "%s :You are now %s %s", nick.c_str(), strchr("aeiouAEIOU", info->name[0]) ? "an" : "a", info->NameStr());
+
+       ServerInstance->Logs->Log("OPER", DEFAULT, "%s!%s@%s opered as type: %s", this->nick.c_str(), this->ident.c_str(), this->host.c_str(), info->NameStr());
        ServerInstance->Users->all_opers.push_back(this);
 
        if (IS_LOCAL(this))
                IS_LOCAL(this)->OperInternal();
 
-       FOREACH_MOD(I_OnPostOper,OnPostOper(this, opertype, opername));
+       FOREACH_MOD(I_OnPostOper,OnPostOper(this, info->name, opername));
 }
 
 void LocalUser::OperInternal()
 {
-       /*
-        * This might look like it's in the wrong place.
-        * It is *not*!
-        *
-        * For multi-network servers, we may not have the opertypes of the remote server, but we still want to mark the user as an oper of that type.
-        * -- w00t
-        */
-       TagIndex::iterator iter_opertype = ServerInstance->Config->opertypes.find(this->oper.c_str());
-       if (iter_opertype != ServerInstance->Config->opertypes.end())
-       {
-               if (AllowedOperCommands)
-                       AllowedOperCommands->clear();
-               else
-                       AllowedOperCommands = new std::set<std::string>;
+       if (AllowedOperCommands)
+               AllowedOperCommands->clear();
+       else
+               AllowedOperCommands = new std::set<std::string>;
 
-               if (AllowedPrivs)
-                       AllowedPrivs->clear();
-               else
-                       AllowedPrivs = new std::set<std::string>;
+       if (AllowedPrivs)
+               AllowedPrivs->clear();
+       else
+               AllowedPrivs = new std::set<std::string>;
 
-               AllowedUserModes.reset();
-               AllowedChanModes.reset();
-               this->AllowedUserModes['o' - 'A'] = true; // Call me paranoid if you want.
+       AllowedUserModes.reset();
+       AllowedChanModes.reset();
+       this->AllowedUserModes['o' - 'A'] = true; // Call me paranoid if you want.
 
-               std::string myclass, mycmd, mypriv;
-               irc::spacesepstream Classes(iter_opertype->second->getString("classes"));
-               while (Classes.GetToken(myclass))
+       for(std::vector<reference<ConfigTag> >::iterator iter = oper->class_blocks.begin(); iter != oper->class_blocks.end(); ++iter)
+       {
+               ConfigTag* tag = *iter;
+               std::string mycmd, mypriv;
+               /* Process commands */
+               irc::spacesepstream CommandList(tag->getString("commands"));
+               while (CommandList.GetToken(mycmd))
                {
-                       TagIndex::iterator iter_operclass = ServerInstance->Config->operclass.find(myclass.c_str());
-                       if (iter_operclass != ServerInstance->Config->operclass.end())
-                       {
-                               /* Process commands */
-                               irc::spacesepstream CommandList(iter_operclass->second->getString("commands"));
-                               while (CommandList.GetToken(mycmd))
-                               {
-                                       this->AllowedOperCommands->insert(mycmd);
-                               }
+                       this->AllowedOperCommands->insert(mycmd);
+               }
 
-                               irc::spacesepstream PrivList(iter_operclass->second->getString("privs"));
-                               while (PrivList.GetToken(mypriv))
-                               {
-                                       this->AllowedPrivs->insert(mypriv);
-                               }
+               irc::spacesepstream PrivList(tag->getString("privs"));
+               while (PrivList.GetToken(mypriv))
+               {
+                       this->AllowedPrivs->insert(mypriv);
+               }
 
-                               for (unsigned char* c = (unsigned char*)iter_operclass->second->getString("usermodes").c_str(); *c; ++c)
-                               {
-                                       if (*c == '*')
-                                       {
-                                               this->AllowedUserModes.set();
-                                       }
-                                       else
-                                       {
-                                               this->AllowedUserModes[*c - 'A'] = true;
-                                       }
-                               }
+               for (unsigned char* c = (unsigned char*)tag->getString("usermodes").c_str(); *c; ++c)
+               {
+                       if (*c == '*')
+                       {
+                               this->AllowedUserModes.set();
+                       }
+                       else
+                       {
+                               this->AllowedUserModes[*c - 'A'] = true;
+                       }
+               }
 
-                               for (unsigned char* c = (unsigned char*)iter_operclass->second->getString("chanmodes").c_str(); *c; ++c)
-                               {
-                                       if (*c == '*')
-                                       {
-                                               this->AllowedChanModes.set();
-                                       }
-                                       else
-                                       {
-                                               this->AllowedChanModes[*c - 'A'] = true;
-                                       }
-                               }
+               for (unsigned char* c = (unsigned char*)tag->getString("chanmodes").c_str(); *c; ++c)
+               {
+                       if (*c == '*')
+                       {
+                               this->AllowedChanModes.set();
+                       }
+                       else
+                       {
+                               this->AllowedChanModes[*c - 'A'] = true;
                        }
                }
        }
@@ -743,7 +733,7 @@ void User::UnOper()
         * note, order is important - this must come before modes as -o attempts
         * to call UnOper. -- w00t
         */
-       this->oper.clear();
+       oper = NULL;
 
 
        /* Remove all oper only modes from the user when the deoper - Bug #466*/
index 29056644679b82621b2ec37005a3b4b3c4d195d0..1f21553c5b1ca89ee9e2e4baa5dce10d336ed8db 100644 (file)
@@ -53,7 +53,7 @@ void InspIRCd::DoWhois(User* user, User* dest,unsigned long signon, unsigned lon
                if (this->Config->GenericOper)
                        this->SendWhoisLine(user, dest, 313, "%s %s :is an IRC operator",user->nick.c_str(), dest->nick.c_str());
                else
-                       this->SendWhoisLine(user, dest, 313, "%s %s :is %s %s on %s",user->nick.c_str(), dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper[0]) ? "an" : "a"),irc::Spacify(dest->oper.c_str()), this->Config->Network.c_str());
+                       this->SendWhoisLine(user, dest, 313, "%s %s :is %s %s on %s",user->nick.c_str(), dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->NameStr(), this->Config->Network.c_str());
        }
 
        if (user == dest || user->HasPrivPermission("users/auspex"))