diff options
| author | 2010-02-25 21:37:06 -0600 | |
|---|---|---|
| committer | 2010-08-03 17:32:37 -0400 | |
| commit | 4cd83bef1e6b0e6f1f779b7f97c74f603a18b768 (patch) | |
| tree | 22b1636eb1c24ca01fc86d43be463a017fa4ba4f /src/modules/m_opflags.cpp | |
| parent | Add 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.cpp | 230 |
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> ¶meters, 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 ¶meter, 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> ¶meters, 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); } }; |
