Change User::oper to an OperInfo reference

git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11945 e03df62e-2008-0410-955e-edbf42e46eb7
This commit is contained in:
danieldg 2009-10-21 23:45:44 +00:00
parent ff3eef491a
commit a30abe26fc
20 changed files with 209 additions and 231 deletions

View 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
/** Oper block and type index.
* For anonymous oper blocks (type only), prefix with a space.
*/
TagIndex opertypes;
/** All oper class definitions from the config file
*/
TagIndex operclass;
OperIndex oper_blocks;
/** Saved argv from startup
*/

View 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())

View 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;
}
}

View 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)

View 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)

View 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
{

View 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 */

View 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);

View 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)

View 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;

View 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())
{

View 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());

View 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);

View 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())
{

View 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))

View 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);

View File

@ -275,26 +275,21 @@ public:
bool OperUser(User* user, const std::string &pattern, const std::string &type)
{
ConfigReader Conf;
OperIndex::iterator iter = ServerInstance->Config->oper_blocks.find(" " + type);
if (iter == ServerInstance->Config->oper_blocks.end())
return false;
OperInfo* ifo = iter->second;
for (int j = 0; j < Conf.Enumerate("type"); j++)
std::string hostname(user->ident);
hostname.append("@").append(user->host);
if (OneOfMatches(hostname.c_str(), user->GetIPString(), pattern.c_str()))
{
std::string tname = Conf.ReadValue("type","name",j);
std::string hostname(user->ident);
/* Opertype and host match, looks like this is it. */
hostname.append("@").append(user->host);
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);
if (operhost.size())
user->ChangeDisplayedHost(operhost.c_str());
user->Oper(type, tname);
return true;
}
user->Oper(ifo);
return true;
}
return false;

View 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;

View 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 (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.
for(std::vector<reference<ConfigTag> >::iterator iter = oper->class_blocks.begin(); iter != oper->class_blocks.end(); ++iter)
{
if (AllowedOperCommands)
AllowedOperCommands->clear();
else
AllowedOperCommands = 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.
std::string myclass, mycmd, mypriv;
irc::spacesepstream Classes(iter_opertype->second->getString("classes"));
while (Classes.GetToken(myclass))
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())
this->AllowedOperCommands->insert(mycmd);
}
irc::spacesepstream PrivList(tag->getString("privs"));
while (PrivList.GetToken(mypriv))
{
this->AllowedPrivs->insert(mypriv);
}
for (unsigned char* c = (unsigned char*)tag->getString("usermodes").c_str(); *c; ++c)
{
if (*c == '*')
{
/* Process commands */
irc::spacesepstream CommandList(iter_operclass->second->getString("commands"));
while (CommandList.GetToken(mycmd))
{
this->AllowedOperCommands->insert(mycmd);
}
this->AllowedUserModes.set();
}
else
{
this->AllowedUserModes[*c - 'A'] = true;
}
}
irc::spacesepstream PrivList(iter_operclass->second->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*)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*/

View 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"))