The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download | Blog | Stats
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 #include "users.h"
00016 #include "channels.h"
00017 #include "modules.h"
00018 
00019 /* $ModDesc: Allows for auditorium channels (+u) where nobody can see others joining and parting or the nick list */
00020 
00021 class AuditoriumMode : public ModeHandler
00022 {
00023  public:
00024         AuditoriumMode(InspIRCd* Instance) : ModeHandler(Instance, 'u', 0, 0, false, MODETYPE_CHANNEL, false) { }
00025 
00026         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
00027         {
00028                 if (channel->IsModeSet('u') != adding)
00029                 {
00030                         if (IS_LOCAL(source) && (channel->GetStatus(source) < STATUS_OP))
00031                         {
00032                                 source->WriteServ("482 %s %s :Only channel operators may %sset channel mode +u", source->nick, channel->name, adding ? "" : "un");
00033                                 return MODEACTION_DENY;
00034                         }
00035                         else
00036                         {
00037                                 channel->SetMode('u', adding);
00038                                 return MODEACTION_ALLOW;
00039                         }
00040                 }
00041                 else
00042                 {
00043                         return MODEACTION_DENY;
00044                 }
00045         }
00046 };
00047 
00048 class ModuleAuditorium : public Module
00049 {
00050  private:
00051         AuditoriumMode* aum;
00052         bool ShowOps;
00053         CUList nl;
00054  public:
00055         ModuleAuditorium(InspIRCd* Me)
00056                 : Module(Me)
00057         {
00058                 aum = new AuditoriumMode(ServerInstance);
00059                 if (!ServerInstance->AddMode(aum, 'u'))
00060                 {
00061                         delete aum;
00062                         throw ModuleException("Could not add new modes!");
00063                 }
00064                 OnRehash(NULL, "");
00065         }
00066         
00067         virtual ~ModuleAuditorium()
00068         {
00069                 ServerInstance->Modes->DelMode(aum);
00070                 DELETE(aum);
00071         }
00072 
00073         virtual void OnRehash(userrec* user, const std::string &parameter)
00074         {
00075                 ConfigReader conf(ServerInstance);
00076                 ShowOps = conf.ReadFlag("auditorium", "showops", 0);
00077         }
00078 
00079         Priority Prioritize()
00080         {
00081                 /* To ensure that we get priority over namesx for names list generation on +u channels */
00082                 return PRIORITY_FIRST;
00083         }
00084 
00085         virtual Version GetVersion()
00086         {
00087                 return Version(1, 1, 0, 0, VF_COMMON | VF_VENDOR, API_VERSION);
00088         }
00089 
00090         void Implements(char* List)
00091         {
00092                 List[I_OnUserJoin] = List[I_OnUserPart] = List[I_OnUserKick] = List[I_OnUserQuit] = List[I_OnUserList] = List[I_OnRehash] = 1;
00093         }
00094 
00095         virtual int OnUserList(userrec* user, chanrec* Ptr, CUList* &nameslist)
00096         {
00097                 if (Ptr->IsModeSet('u'))
00098                 {
00099                         ServerInstance->Log(DEBUG,"AUDITORIUM: nameslist: %08lx", nameslist);
00100                         if (ShowOps)
00101                         {
00102                                 /* Leave the names list alone, theyre an op
00103                                  * doing /names on the channel after joining it
00104                                  */
00105                                 if (Ptr->GetStatus(user) >= STATUS_OP)
00106                                 {
00107                                         nameslist = Ptr->GetUsers();
00108                                         ServerInstance->Log(DEBUG,"AUDITORIUM: new nameslist: %08lx", nameslist);
00109                                         return 0;
00110                                 }
00111 
00112                                 /* Show all the opped users */
00113                                 nl = *(Ptr->GetOppedUsers());
00114                                 nl[user] = user->nick;
00115                                 nameslist = &nl;
00116                                 ServerInstance->Log(DEBUG,"AUDITORIUM: new nameslist: %08lx", nameslist);
00117                                 return 0;
00118                         }
00119                         else
00120                         {
00121                                 /* HELLOOO, IS ANYBODY THERE? -- nope, just us. */
00122                                 user->WriteServ("353 %s %c %s :%s", user->nick, Ptr->IsModeSet('s') ? '@' : Ptr->IsModeSet('p') ? '*' : '=', Ptr->name, user->nick);
00123                                 user->WriteServ("366 %s %s :End of /NAMES list.", user->nick, Ptr->name);
00124                                 return 1;
00125                         }
00126                 }
00127                 return 0;
00128         }
00129         
00130         virtual void OnUserJoin(userrec* user, chanrec* channel, bool &silent)
00131         {
00132                 if (channel->IsModeSet('u'))
00133                 {
00134                         silent = true;
00135                         /* Because we silenced the event, make sure it reaches the user whos joining (but only them of course) */
00136                         user->WriteFrom(user, "JOIN %s", channel->name);
00137                         if (ShowOps)
00138                                 channel->WriteAllExceptSender(user, false, channel->GetStatus(user) >= STATUS_OP ? 0 : '@', "JOIN %s", channel->name);
00139                 }
00140         }
00141 
00142         void OnUserPart(userrec* user, chanrec* channel, const std::string &partmessage, bool &silent)
00143         {
00144                 if (channel->IsModeSet('u'))
00145                 {
00146                         silent = true;
00147                         /* Because we silenced the event, make sure it reaches the user whos leaving (but only them of course) */
00148                         user->WriteFrom(user, "PART %s%s%s", channel->name,
00149                                         partmessage.empty() ? "" : " :",
00150                                         partmessage.empty() ? "" : partmessage.c_str());
00151                         if (ShowOps)
00152                         {
00153                                 channel->WriteAllExceptSender(user, false, channel->GetStatus(user) >= STATUS_OP ? 0 : '@', "PART %s%s%s", channel->name, partmessage.empty() ? "" : " :",
00154                                                 partmessage.empty() ? "" : partmessage.c_str());
00155                         }
00156                 }
00157         }
00158 
00159         void OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason, bool &silent)
00160         {
00161                 if (chan->IsModeSet('u'))
00162                 {
00163                         silent = true;
00164                         /* Send silenced event only to the user being kicked and the user doing the kick */
00165                         source->WriteFrom(source, "KICK %s %s %s", chan->name, user->nick, reason.c_str());
00166                         if (ShowOps)
00167                                 chan->WriteAllExceptSender(source, false, chan->GetStatus(user) >= STATUS_OP ? 0 : '@', "KICK %s %s %s", chan->name, user->nick, reason.c_str());
00168                         if ((!ShowOps) || (chan->GetStatus(user) < STATUS_OP)) /* make sure the kicked user always gets the message */
00169                                 user->WriteFrom(source, "KICK %s %s %s", chan->name, user->nick, reason.c_str());
00170                 }
00171         }
00172 
00173         void OnUserQuit(userrec* user, const std::string &reason, const std::string &oper_message)
00174         {
00175                 command_t* parthandler = ServerInstance->Parser->GetHandler("PART");
00176                 std::vector<std::string> to_leave;
00177                 const char* parameters[2];
00178                 if (parthandler)
00179                 {
00180                         for (UCListIter f = user->chans.begin(); f != user->chans.end(); f++)
00181                         {
00182                                 if (f->first->IsModeSet('u'))
00183                                         to_leave.push_back(f->first->name);
00184                         }
00185                         /* We cant do this neatly in one loop, as we are modifying the map we are iterating */
00186                         for (std::vector<std::string>::iterator n = to_leave.begin(); n != to_leave.end(); n++)
00187                         {
00188                                 parameters[0] = n->c_str();
00189                                 /* This triggers our OnUserPart, above, making the PART silent */
00190                                 parthandler->Handle(parameters, 1, user);
00191                         }
00192                 }
00193         }
00194 };
00195 
00196 MODULE_INIT(ModuleAuditorium)