]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_auditorium.cpp
m_dccallow Validate tokens before use
[user/henk/code/inspircd.git] / src / modules / m_auditorium.cpp
index 4dec57df9460ad489ad5d8d5307c7069d2eccc05..2a8edb9d49f1a464eb26fe597817073b44b1ba18 100644 (file)
@@ -1,16 +1,25 @@
-/*       +------------------------------------+
- *       | Inspire Internet Relay Chat Daemon |
- *       +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
  *
- *  InspIRCd: (C) 2002-2010 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
+ *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+ *   Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc>
+ *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
  *
- * This program is free but copyrighted software; see
- *            the file COPYING for details.
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
  *
- * ---------------------------------------------------
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+
 #include "inspircd.h"
 
 /* $ModDesc: Allows for auditorium channels (+u) where nobody can see others joining and parting or the nick list */
@@ -25,15 +34,10 @@ class AuditoriumMode : public ModeHandler
 
        ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
        {
-               if (channel->IsModeSet('u') != adding)
-               {
-                       channel->SetMode('u', adding);
-                       return MODEACTION_ALLOW;
-               }
-               else
-               {
+               if (channel->IsModeSet(this) == adding)
                        return MODEACTION_DENY;
-               }
+               channel->SetMode(this, adding);
+               return MODEACTION_ALLOW;
        }
 };
 
@@ -41,20 +45,25 @@ class ModuleAuditorium : public Module
 {
  private:
        AuditoriumMode aum;
-       bool ShowOps;
-       bool OperOverride;
+       bool OpsVisible;
+       bool OpsCanSee;
+       bool OperCanSee;
  public:
-       ModuleAuditorium()
-               : aum(this)
+       ModuleAuditorium() : aum(this)
        {
-               if (!ServerInstance->Modes->AddMode(&aum))
-                       throw ModuleException("Could not add new modes!");
+       }
 
-               OnRehash(NULL);
+       void init()
+       {
+               ServerInstance->Modules->AddService(aum);
 
-               Implementation eventlist[] = { I_OnUserJoin, I_OnUserPart, I_OnUserKick, I_OnBuildNeighborList, I_OnNamesListItem, I_OnRehash };
-               ServerInstance->Modules->Attach(eventlist, this, 6);
+               OnRehash(NULL);
 
+               Implementation eventlist[] = {
+                       I_OnUserJoin, I_OnUserPart, I_OnUserKick,
+                       I_OnBuildNeighborList, I_OnNamesListItem, I_OnSendWhoLine,
+                       I_OnRehash };
+               ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
        }
 
        ~ModuleAuditorium()
@@ -63,9 +72,10 @@ class ModuleAuditorium : public Module
 
        void OnRehash(User* user)
        {
-               ConfigReader conf;
-               ShowOps = conf.ReadFlag("auditorium", "showops", 0);
-               OperOverride = conf.ReadFlag("auditorium", "operoverride", 0);
+               ConfigTag* tag = ServerInstance->Config->ConfValue("auditorium");
+               OpsVisible = tag->getBool("opvisible");
+               OpsCanSee = tag->getBool("opcansee");
+               OperCanSee = tag->getBool("opercansee", true);
        }
 
        Version GetVersion()
@@ -73,55 +83,64 @@ class ModuleAuditorium : public Module
                return Version("Allows for auditorium channels (+u) where nobody can see others joining and parting or the nick list", VF_VENDOR);
        }
 
-       void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick)
+       /* Can they be seen by everyone? */
+       bool IsVisible(Membership* memb)
        {
-               if (!memb->chan->IsModeSet('u'))
-                       return;
+               if (!memb->chan->IsModeSet(&aum))
+                       return true;
+
+               ModResult res = ServerInstance->OnCheckExemption(memb->user, memb->chan, "auditorium-vis");
+               return res.check(OpsVisible && memb->getRank() >= OP_VALUE);
+       }
+
+       /* Can they see this specific membership? */
+       bool CanSee(User* issuer, Membership* memb)
+       {
+               // If user is oper and operoverride is on, don't touch the list
+               if (OperCanSee && issuer->HasPrivPermission("channels/auspex"))
+                       return true;
+
+               // You can always see yourself
+               if (issuer == memb->user)
+                       return true;
+
+               // Can you see the list by permission?
+               ModResult res = ServerInstance->OnCheckExemption(issuer,memb->chan,"auditorium-see");
+               if (res.check(OpsCanSee && memb->chan->GetPrefixValue(issuer) >= OP_VALUE))
+                       return true;
+
+               return false;
+       }
 
-               /* Some module hid this from being displayed, dont bother */
+       void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick)
+       {
+               // Some module already hid this from being displayed, don't bother
                if (nick.empty())
                        return;
 
-               /* If user is oper and operoverride is on, don't touch the list */
-               if (OperOverride && issuer->HasPrivPermission("channels/auspex"))
+               if (IsVisible(memb))
                        return;
 
-               if (ShowOps && (issuer != memb->user) && (memb->getRank() < OP_VALUE))
-               {
-                       /* Showops is set, hide all non-ops from the user, except themselves */
-                       nick.clear();
+               if (CanSee(issuer, memb))
                        return;
-               }
 
-               if (!ShowOps && (issuer != memb->user))
-               {
-                       /* ShowOps is not set, hide everyone except the user whos requesting NAMES */
-                       nick.clear();
-                       return;
-               }
+               nick.clear();
        }
 
+       /** Build CUList for showing this join/part/kick */
        void BuildExcept(Membership* memb, CUList& excepts)
        {
-               if (!memb->chan->IsModeSet('u'))
-                       return;
-               if (ShowOps && memb->getRank() >= OP_VALUE)
+               if (IsVisible(memb))
                        return;
 
                const UserMembList* users = memb->chan->GetUsers();
                for(UserMembCIter i = users->begin(); i != users->end(); i++)
                {
-                       if (i->first == memb->user || !IS_LOCAL(i->first))
-                               continue;
-                       if (ShowOps && i->second->getRank() >= OP_VALUE)
-                               continue;
-                       if (OperOverride && i->first->HasPrivPermission("channels/auspex"))
-                               continue;
-                       // This is a different user in the channel, local, and not op/oper
-                       // so, hide the join from them
-                       excepts.insert(i->first);
+                       if (IS_LOCAL(i->first) && !CanSee(i->first, memb))
+                               excepts.insert(i->first);
                }
        }
+
        void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts)
        {
                BuildExcept(memb, excepts);
@@ -143,10 +162,33 @@ class ModuleAuditorium : public Module
                while (i != include.end())
                {
                        Channel* c = *i++;
-                       if (c->IsModeSet('u'))
-                               include.erase(c);
+                       Membership* memb = c->GetUser(source);
+                       if (!memb || IsVisible(memb))
+                               continue;
+                       // this channel should not be considered when listing my neighbors
+                       include.erase(c);
+                       // however, that might hide me from ops that can see me...
+                       const UserMembList* users = c->GetUsers();
+                       for(UserMembCIter j = users->begin(); j != users->end(); j++)
+                       {
+                               if (IS_LOCAL(j->first) && CanSee(j->first, memb))
+                                       exception[j->first] = true;
+                       }
                }
        }
+
+       void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line)
+       {
+               Channel* channel = ServerInstance->FindChan(params[0]);
+               if (!channel)
+                       return;
+               Membership* memb = channel->GetUser(user);
+               if ((!memb) || (IsVisible(memb)))
+                       return;
+               if (CanSee(source, memb))
+                       return;
+               line.clear();
+       }
 };
 
 MODULE_INIT(ModuleAuditorium)