diff options
-rw-r--r-- | include/modules.h | 4 | ||||
-rw-r--r-- | src/channels.cpp | 8 | ||||
-rw-r--r-- | src/modules/m_spy.cpp | 104 |
3 files changed, 27 insertions, 89 deletions
diff --git a/include/modules.h b/include/modules.h index 112804524..1e2d1e3c5 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1271,7 +1271,9 @@ class CoreExport Module : public Extensible * @param userlist The user list for the channel (you may change this pointer. * If you want to change the values, take a copy first, and change the copy, then * point the pointer at your copy) - * @return 1 to prevent the user list being sent to the client, 0 to allow it + * @return 1 to prevent the user list being sent to the client, 0 to allow it. + * Returning -1 allows the names list, but bypasses any checks which check for + * channel membership before sending the names list. */ virtual int OnUserList(User* user, Channel* Ptr, CUList* &userlist); diff --git a/src/channels.cpp b/src/channels.cpp index 764126891..14f0f55f1 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -835,6 +835,14 @@ void Channel::UserList(User *user, CUList *ulist) FOREACH_RESULT(I_OnUserList,OnUserList(user, this, ulist)); if (MOD_RESULT == 1) return; + if (MOD_RESULT != -1) + { + if ((this->IsModeSet('s')) && (!this->HasUser(user))) + { + user->WriteServ("401 %s %s :No such nick/channel",user->nick, this->name); + return; + } + } dlen = curlen = snprintf(list,MAXBUF,"353 %s %c %s :", user->nick, this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name); diff --git a/src/modules/m_spy.cpp b/src/modules/m_spy.cpp index 7420d6d3c..e44deb93b 100644 --- a/src/modules/m_spy.cpp +++ b/src/modules/m_spy.cpp @@ -6,110 +6,38 @@ * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see - * the file COPYING for details. + * the file COPYING for details. * * --------------------------------------------------- */ -/* $ModDesc: Provides SPYLIST and SPYNAMES capability, allowing opers to see who's in +s channels */ +/* $ModDesc: Provides the ability to see the complete names list of channels an oper is not a member of */ #include "inspircd.h" #include "wildcard.h" -void spy_userlist(User *user, Channel *c) -{ - char list[MAXBUF]; - size_t dlen, curlen; - - dlen = curlen = snprintf(list,MAXBUF,"353 %s %c %s :", user->nick, c->IsModeSet('s') ? '@' : c->IsModeSet('p') ? '*' : '=', c->name); - - int numusers = 0; - char* ptr = list + dlen; - - CUList *ulist= c->GetUsers(); - - for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++) - { - size_t ptrlen = snprintf(ptr, MAXBUF, "%s%s ", c->GetPrefixChar(i->first), i->first->nick); - - curlen += ptrlen; - ptr += ptrlen; - - numusers++; - - if (curlen > (480-NICKMAX)) - { - /* list overflowed into multiple numerics */ - user->WriteServ(std::string(list)); - - /* reset our lengths */ - dlen = curlen = snprintf(list,MAXBUF,"353 %s %c %s :", user->nick, c->IsModeSet('s') ? '@' : c->IsModeSet('p') ? '*' : '=', c->name); - ptr = list + dlen; - - ptrlen = 0; - numusers = 0; - } - } - - /* if whats left in the list isnt empty, send it */ - if (numusers) - { - user->WriteServ(std::string(list)); - } - - user->WriteServ("366 %s %s :End of /NAMES list.", user->nick, c->name); - -} - -/** Handle /SPYNAMES - */ -class CommandSpynames : public Command +class ModuleSpy : public Module { - public: - CommandSpynames (InspIRCd* Instance) : Command(Instance,"SPYNAMES", 'o', 0) + public: + ModuleSpy(InspIRCd* Me) : Module(Me) { - this->source = "m_spy.so"; - syntax = "{<channel>{,<channel>}}"; + ServerInstance->Modules->Attach(I_OnUserList, this); } - CmdResult Handle (const char** parameters, int pcnt, User *user) + virtual int OnUserList(User* user, Channel* Ptr, CUList* &nameslist) { - Channel* c = NULL; - - if (!pcnt) - { - user->WriteServ("366 %s * :End of /NAMES list.",user->nick); - return CMD_FAILURE; - } - - if (ServerInstance->Parser->LoopCall(user, this, parameters, pcnt, 0)) - return CMD_FAILURE; + /* User is an oper and is NOT on the channel */ + if (IS_OPER(user) && !Ptr->HasUser(user)) + return -1; - c = ServerInstance->FindChan(parameters[0]); - if (c) - { - ServerInstance->WriteOpers("*** Oper %s used SPYNAMES to view the users on %s", user->nick, parameters[0]); - spy_userlist(user,c); - } - else - { - user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]); - } - - return CMD_LOCALONLY; + return 0; } -}; - -class ModuleSpy : public Module -{ - CommandSpynames *mycommand2; - public: - ModuleSpy(InspIRCd* Me) : Module(Me) - { - - mycommand2 = new CommandSpynames(ServerInstance); - ServerInstance->AddCommand(mycommand2); + void Prioritize() + { + /* To ensure that we get priority over namesx and delayjoin for names list generation */ + Module* list[] = { ServerInstance->Modules->Find("m_namesx.so"), ServerInstance->Modules->Find("m_delayjoin.so") }; + ServerInstance->Modules->SetPriority(this, I_OnUserList, PRIO_BEFORE, list, 2); } virtual ~ModuleSpy() |