The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

m_auditorium.cpp

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
00006  * See: http://www.inspircd.org/wiki/index.php/Credits
00007  *
00008  * This program is free but copyrighted software; see
00009  *            the file COPYING for details.
00010  *
00011  * ---------------------------------------------------
00012  */
00013 
00014 #include "inspircd.h"
00015 
00016 /* $ModDesc: Allows for auditorium channels (+u) where nobody can see others joining and parting or the nick list */
00017 
00018 class AuditoriumMode : public ModeHandler
00019 {
00020  public:
00021         AuditoriumMode(InspIRCd* Instance) : ModeHandler(Instance, 'u', 0, 0, false, MODETYPE_CHANNEL, false) { }
00022 
00023         ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding, bool)
00024         {
00025                 if (channel->IsModeSet('u') != adding)
00026                 {
00027                         if (IS_LOCAL(source) && (channel->GetStatus(source) < STATUS_OP))
00028                         {
00029                                 source->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only channel operators may %sset channel mode +u", source->nick.c_str(), channel->name.c_str(), adding ? "" : "un");
00030                                 return MODEACTION_DENY;
00031                         }
00032                         else
00033                         {
00034                                 channel->SetMode('u', adding);
00035                                 return MODEACTION_ALLOW;
00036                         }
00037                 }
00038                 else
00039                 {
00040                         return MODEACTION_DENY;
00041                 }
00042         }
00043 };
00044 
00045 class ModuleAuditorium : public Module
00046 {
00047  private:
00048         AuditoriumMode* aum;
00049         bool ShowOps;
00050         bool OperOverride;
00051         CUList nl;
00052         CUList except_list;
00053  public:
00054         ModuleAuditorium(InspIRCd* Me)
00055                 : Module(Me)
00056         {
00057                 aum = new AuditoriumMode(ServerInstance);
00058                 if (!ServerInstance->Modes->AddMode(aum))
00059                 {
00060                         delete aum;
00061                         throw ModuleException("Could not add new modes!");
00062                 }
00063 
00064                 OnRehash(NULL, "");
00065 
00066                 Implementation eventlist[] = { I_OnUserJoin, I_OnUserPart, I_OnUserKick, I_OnUserQuit, I_OnNamesListItem, I_OnRehash };
00067                 Me->Modules->Attach(eventlist, this, 6);
00068 
00069         }
00070 
00071         virtual ~ModuleAuditorium()
00072         {
00073                 ServerInstance->Modes->DelMode(aum);
00074                 delete aum;
00075         }
00076 
00077         virtual void OnRehash(User* user, const std::string &parameter)
00078         {
00079                 ConfigReader conf(ServerInstance);
00080                 ShowOps = conf.ReadFlag("auditorium", "showops", 0);
00081                 OperOverride = conf.ReadFlag("auditorium", "operoverride", 0);
00082         }
00083 
00084         virtual Version GetVersion()
00085         {
00086                 return Version("$Id: m_auditorium.cpp 10291 2008-08-25 20:35:51Z w00t $", VF_COMMON | VF_VENDOR, API_VERSION);
00087         }
00088 
00089         virtual void OnNamesListItem(User* issuer, User* user, Channel* channel, std::string &prefixes, std::string &nick)
00090         {
00091                 if (!channel->IsModeSet('u'))
00092                         return;
00093 
00094                 /* Some module hid this from being displayed, dont bother */
00095                 if (nick.empty())
00096                         return;
00097 
00098                 /* If user is oper and operoverride is on, don't touch the list */
00099                 if (OperOverride && IS_OPER(user))
00100                         return;
00101 
00102                 if (ShowOps && (issuer != user) && (channel->GetStatus(user) < STATUS_OP))
00103                 {
00104                         /* Showops is set, hide all non-ops from the user, except themselves */
00105                         nick.clear();
00106                         return;
00107                 }
00108 
00109                 if (!ShowOps && (issuer != user))
00110                 {
00111                         /* ShowOps is not set, hide everyone except the user whos requesting NAMES */
00112                         nick.clear();
00113                         return;
00114                 }
00115         }
00116 
00117         virtual void OnUserJoin(User* user, Channel* channel, bool sync, bool &silent)
00118         {
00119                 if (channel->IsModeSet('u'))
00120                 {
00121                         silent = true;
00122                         /* Because we silenced the event, make sure it reaches the user whos joining (but only them of course) */
00123                         user->WriteFrom(user, "JOIN %s", channel->name.c_str());
00124                         if (ShowOps)
00125                                 channel->WriteAllExcept(user, false, channel->GetStatus(user) >= STATUS_OP ? 0 : '@', except_list, "JOIN %s", channel->name.c_str());
00126                 }
00127         }
00128 
00129         void OnUserPart(User* user, Channel* channel, std::string &partmessage, bool &silent)
00130         {
00131                 if (channel->IsModeSet('u'))
00132                 {
00133                         silent = true;
00134                         /* Because we silenced the event, make sure it reaches the user whos leaving (but only them of course) */
00135                         user->WriteFrom(user, "PART %s%s%s", channel->name.c_str(),
00136                                         partmessage.empty() ? "" : " :",
00137                                         partmessage.empty() ? "" : partmessage.c_str());
00138                         if (ShowOps)
00139                         {
00140                                 channel->WriteAllExcept(user, false, channel->GetStatus(user) >= STATUS_OP ? 0 : '@', except_list, "PART %s%s%s", channel->name.c_str(), partmessage.empty() ? "" : " :",
00141                                                 partmessage.empty() ? "" : partmessage.c_str());
00142                         }
00143                 }
00144         }
00145 
00146         void OnUserKick(User* source, User* user, Channel* chan, const std::string &reason, bool &silent)
00147         {
00148                 if (chan->IsModeSet('u'))
00149                 {
00150                         silent = true;
00151                         /* Send silenced event only to the user being kicked and the user doing the kick */
00152                         source->WriteFrom(source, "KICK %s %s %s", chan->name.c_str(), user->nick.c_str(), reason.c_str());
00153                         if (ShowOps)
00154                                 chan->WriteAllExcept(source, false, chan->GetStatus(source) >= STATUS_OP ? 0 : '@', except_list, "KICK %s %s %s", chan->name.c_str(), user->nick.c_str(), reason.c_str());
00155                         else
00156                                 user->WriteFrom(source, "KICK %s %s %s", chan->name.c_str(), user->nick.c_str(), reason.c_str());
00157                 }
00158         }
00159 
00160         void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
00161         {
00162                 Command* parthandler = ServerInstance->Parser->GetHandler("PART");
00163                 std::vector<std::string> to_leave;
00164                 if (parthandler)
00165                 {
00166                         for (UCListIter f = user->chans.begin(); f != user->chans.end(); f++)
00167                         {
00168                                 if (f->first->IsModeSet('u'))
00169                                         to_leave.push_back(f->first->name);
00170                         }
00171                         /* We cant do this neatly in one loop, as we are modifying the map we are iterating */
00172                         for (std::vector<std::string>::iterator n = to_leave.begin(); n != to_leave.end(); n++)
00173                         {
00174                                 std::vector<std::string> parameters;
00175                                 parameters.push_back(*n);
00176                                 /* This triggers our OnUserPart, above, making the PART silent */
00177                                 parthandler->Handle(parameters, user);
00178                         }
00179                 }
00180         }
00181 };
00182 
00183 MODULE_INIT(ModuleAuditorium)