aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/m_opflags.cpp
diff options
context:
space:
mode:
authorGravatar Daniel De Graaf2010-02-25 21:37:06 -0600
committerGravatar Daniel De Graaf2010-08-03 17:32:37 -0400
commit4cd83bef1e6b0e6f1f779b7f97c74f603a18b768 (patch)
tree22b1636eb1c24ca01fc86d43be463a017fa4ba4f /src/modules/m_opflags.cpp
parentAdd OPFLAGS command to allow services to silently change opflags (diff)
Kill channel mode +x, OPFLAGS command is far less confusing
Diffstat (limited to 'src/modules/m_opflags.cpp')
-rw-r--r--src/modules/m_opflags.cpp230
1 files changed, 97 insertions, 133 deletions
diff --git a/src/modules/m_opflags.cpp b/src/modules/m_opflags.cpp
index 1c60a0ddb..831ac281f 100644
--- a/src/modules/m_opflags.cpp
+++ b/src/modules/m_opflags.cpp
@@ -19,14 +19,17 @@
class OpFlagProviderImpl : public OpFlagProvider
{
public:
- SimpleExtItem<std::vector<std::string> > ext;
+ LocalStringExt ext;
OpFlagProviderImpl(Module* parent) : OpFlagProvider(parent, "opflags"), ext("flaglist", parent)
{
}
- const std::vector<std::string>* GetFlags(Membership* memb)
+ std::string GetFlags(Membership* memb)
{
- return ext.get(memb);
+ std::string* v = ext.get(memb);
+ if (v)
+ return *v;
+ return "";
}
bool PermissionCheck(Membership* memb, const std::string& needed)
@@ -44,14 +47,16 @@ class OpFlagProviderImpl : public OpFlagProvider
if (memb->getRank() >= neededrank)
return true;
}
- std::vector<std::string>* mine = ext.get(memb);
+ std::string* mine = ext.get(memb);
if (!mine)
return false;
while (flags.GetToken(flag))
{
- for(std::vector<std::string>::iterator i = mine->begin(); i != mine->end(); i++)
+ irc::commasepstream myflags(*mine);
+ std::string myflag;
+ while (myflags.GetToken(myflag))
{
- if (flag == *i)
+ if (flag == myflag)
return true;
}
}
@@ -59,138 +64,67 @@ class OpFlagProviderImpl : public OpFlagProvider
}
};
-class FlagMode : public ModeHandler
+class FlagCmd : public Command
{
public:
OpFlagProviderImpl prov;
- bool hide;
- FlagMode(Module* parent) : ModeHandler(parent, "opflags", 'x', PARAM_ALWAYS, MODETYPE_CHANNEL),
- prov(parent)
+ FlagCmd(Module* parent) : Command(parent, "OPFLAGS", 2), prov(parent)
{
- fixed_letter = true;
- list = true;
- m_paramtype = TR_CUSTOM;
- levelrequired = OP_VALUE;
+ syntax = "<channel> <nick> {+-=}[<flags>]";
+ TRANSLATE4(TR_TEXT, TR_NICK, TR_TEXT, TR_END);
}
- ModResult AccessCheck(User* src, Channel*, std::string& value, bool adding)
+ CmdResult Handle(const std::vector<std::string> &parameters, User *src)
{
- // TODO remove flags from self
- // TODO maximum size of flag list on a person?
- return MOD_RES_PASSTHRU;
- }
+ Channel* chan = ServerInstance->FindChan(parameters[0]);
+ User* user = ServerInstance->FindNick(parameters[1]);
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
- {
- std::string::size_type colon = parameter.find(':');
- if (colon == std::string::npos)
- return MODEACTION_DENY;
- std::string flag = parameter.substr(0, colon);
- std::string nick = parameter.substr(colon + 1);
- dest = ServerInstance->FindNick(nick);
- if (!dest)
+ if (!user || !chan)
{
- source->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",
- source->nick.c_str(), parameter.c_str());
- return MODEACTION_DENY;
+ src->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",
+ src->nick.c_str(), parameters[chan ? 1 : 0].c_str());
+ return CMD_FAILURE;
}
- Membership* memb = channel->GetUser(dest);
+
+ Membership* memb = chan->GetUser(user);
if (!memb)
- return MODEACTION_DENY;
- std::vector<std::string>* ptr = prov.ext.get(memb);
- if (adding && !ptr)
- prov.ext.set(memb, ptr = new std::vector<std::string>);
- if (!ptr)
- return MODEACTION_ALLOW;
- for(std::vector<std::string>::iterator i = ptr->begin(); i != ptr->end(); i++)
+ return CMD_FAILURE;
+ std::string* ptr = prov.ext.get(memb);
+
+ if (parameters.size() == 2)
{
- if (*i == flag)
- {
- if (adding)
- return MODEACTION_DENY;
- else
- {
- ptr->erase(i);
- if (ptr->empty())
- prov.ext.unset(memb);
- return MODEACTION_ALLOW;
- }
- }
+ src->WriteServ("NOTICE %s :User %s has %s%s", chan->name.c_str(),
+ user->nick.c_str(), ptr ? "opflags " : "no opflags", ptr ? ptr->c_str() : "");
+ return CMD_SUCCESS;
}
- if (adding)
- ptr->push_back(flag);
- return MODEACTION_ALLOW;
- }
- void PopulateChanModes(Channel* channel, irc::modestacker& stack)
- {
- const UserMembList* users = channel->GetUsers();
- for(UserMembCIter u = users->begin(); u != users->end(); u++)
+ if (IS_LOCAL(src))
{
- std::vector<std::string>* ptr = prov.ext.get(u->second);
- if (ptr)
+ ModResult res = ServerInstance->OnCheckExemption(src,chan,"opflags");
+ if (!res.check(chan->GetPrefixValue(src) >= OP_VALUE))
{
- for(std::vector<std::string>::iterator i = ptr->begin(); i != ptr->end(); i++)
- {
- std::string value = *i + ":" + u->first->uuid;
- stack.push(irc::modechange(id, value, true));
- }
+ src->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You cannot change opflags on this channel.",
+ src->nick.c_str(), chan->name.c_str());
+ return CMD_FAILURE;
}
}
- }
- void TranslateMode(std::string& value, bool adding, SerializeFormat format)
- {
- if (format == FORMAT_PERSIST || (hide && format == FORMAT_USER))
+ std::string flag;
+ std::set<std::string> flags;
+ if (ptr)
{
- value.clear();
- return;
+ irc::commasepstream myflags(*ptr);
+ while (myflags.GetToken(flag))
+ flags.insert(flag);
}
-
- std::string::size_type colon = value.find(':');
- if (colon == std::string::npos)
- return;
- std::string flag = value.substr(0, colon + 1);
- std::string nick = value.substr(colon + 1);
- User* dest = ServerInstance->FindNick(nick);
- if (!dest)
- return;
- value = flag + (format == FORMAT_USER ? dest->nick : dest->uuid);
- }
-};
-
-class FlagCmd : public Command
-{
- public:
- FlagMode mode;
- FlagCmd(Module* parent) : Command(parent, "OPFLAGS", 3), mode(parent)
- {
- flags_needed = FLAG_SERVERONLY; // ?
- }
-
- CmdResult Handle(const std::vector<std::string> &parameters, User *src)
- {
- Channel* chan = ServerInstance->FindChan(parameters[0]);
- User* user = ServerInstance->FindNick(parameters[1]);
-
- if (!user || !chan)
- return CMD_FAILURE;
-
- Membership* memb = chan->GetUser(user);
- if (!memb)
- return CMD_FAILURE;
- std::vector<std::string>* ptr = mode.prov.ext.get(memb);
- if (!ptr)
- mode.prov.ext.set(memb, ptr = new std::vector<std::string>);
-
+
bool adding = true;
- irc::commasepstream flags(parameters[2]);
- std::string flag;
- while (flags.GetToken(flag))
+ irc::commasepstream deltaflags(parameters[2]);
+ while (deltaflags.GetToken(flag))
{
if (flag[0] == '=')
{
- ptr->clear();
+ flags.clear();
flag = flag.substr(1);
}
else if (flag[0] == '+' || flag[0] == '-')
@@ -200,26 +134,37 @@ class FlagCmd : public Command
}
if (flag.empty())
continue;
- for(std::vector<std::string>::iterator i = ptr->begin(); i != ptr->end(); i++)
+ if (adding)
+ flags.insert(flag);
+ else
+ flags.erase(flag);
+ }
+ if (flags.empty())
+ {
+ prov.ext.unset(memb);
+ chan->WriteChannelWithServ(src->server, "NOTICE %s :%s removed all opflags from %s",
+ chan->name.c_str(), src->nick.c_str(), user->nick.c_str());
+ }
+ else
+ {
+ std::string v;
+ for(std::set<std::string>::iterator i = flags.begin(); i != flags.end(); i++)
{
- if (*i == flag)
- {
- if (!adding)
- ptr->erase(i);
- goto found;
- }
+ if (i != flags.begin())
+ v.push_back(',');
+ v.append(*i);
}
- if (adding)
- ptr->push_back(flag);
-found: ;
+ prov.ext.set(memb, v);
+ chan->WriteChannelWithServ(src->server, "NOTICE %s :%s set %s opflags to %s",
+ chan->name.c_str(), src->nick.c_str(), user->nick.c_str(), v.c_str());
}
- if (ptr->empty())
- mode.prov.ext.unset(memb);
return CMD_SUCCESS;
}
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
{
+ if (parameters.size() == 2)
+ return ROUTE_LOCALONLY;
return ROUTE_OPT_BCAST;
}
};
@@ -235,24 +180,43 @@ class ModuleOpFlags : public Module
void init()
{
ServerInstance->Modules->AddService(cmd);
- ServerInstance->Modules->AddService(cmd.mode);
- ServerInstance->Modules->AddService(cmd.mode.prov);
- ServerInstance->Modules->AddService(cmd.mode.prov.ext);
+ ServerInstance->Modules->AddService(cmd.prov);
+ ServerInstance->Modules->AddService(cmd.prov.ext);
OnRehash(NULL);
- Implementation eventlist[] = { I_OnRehash };
- ServerInstance->Modules->Attach(eventlist, this, 1);
+ Implementation eventlist[] = { I_OnRehash, I_OnSyncChannel };
+ ServerInstance->Modules->Attach(eventlist, this, 2);
}
void OnRehash(User*)
{
- ConfigTag* tag = ServerInstance->Config->ConfValue("opflags");
- cmd.mode.hide = tag->getBool("hidden");
+ // ConfigTag* tag = ServerInstance->Config->ConfValue("opflags");
+ // TODO maxflags?
}
+ void OnSyncChannel(Channel* channel, SyncTarget* target)
+ {
+ const UserMembList* users = channel->GetUsers();
+ for(UserMembCIter u = users->begin(); u != users->end(); u++)
+ {
+ std::string* ptr = cmd.prov.ext.get(u->second);
+ if (ptr)
+ {
+ parameterlist flags;
+ flags.push_back("*");
+ flags.push_back("OPFLAGS");
+ flags.push_back(channel->name);
+ flags.push_back(u->first->uuid);
+ flags.push_back(*ptr);
+ target->SendEncap(flags);
+ }
+ }
+ }
+
+
Version GetVersion()
{
- return Version("Provides per-channel access flags", VF_VENDOR);
+ return Version("Provides per-channel access flags", VF_OPTCOMMON | VF_VENDOR);
}
};