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_denychans.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: Implements config tags which allow blocking of joins to channels */
00017 
00018 class ModuleDenyChannels : public Module
00019 {
00020  private:
00021 
00022 
00023         ConfigReader *Conf;
00024 
00025  public:
00026         ModuleDenyChannels(InspIRCd* Me) : Module(Me)
00027         {
00028 
00029                 Conf = new ConfigReader(ServerInstance);
00030                 Implementation eventlist[] = { I_OnUserPreJoin, I_OnRehash };
00031                 ServerInstance->Modules->Attach(eventlist, this, 2);
00032         }
00033 
00034         virtual void OnRehash(User* user, const std::string &param)
00035         {
00036                 delete Conf;
00037                 Conf = new ConfigReader(ServerInstance);
00038                 /* check for redirect validity and loops/chains */
00039                 for (int i =0; i < Conf->Enumerate("badchan"); i++)
00040                 {
00041                         std::string name = Conf->ReadValue("badchan","name",i);
00042                         std::string redirect = Conf->ReadValue("badchan","redirect",i);
00043 
00044                         if (!redirect.empty())
00045                         {
00046 
00047                                 if (!ServerInstance->IsChannel(redirect.c_str(), ServerInstance->Config->Limits.ChanMax))
00048                                 {
00049                                         if (user)
00050                                                 user->WriteServ("NOTICE %s :Invalid badchan redirect '%s'", user->nick.c_str(), redirect.c_str());
00051                                         throw ModuleException("Invalid badchan redirect, not a channel");
00052                                 }
00053 
00054                                 for (int j =0; j < Conf->Enumerate("badchan"); j++)
00055                                 {
00056                                         if (InspIRCd::Match(redirect, Conf->ReadValue("badchan","name",j)))
00057                                         {
00058                                                 bool goodchan = false;
00059                                                 for (int k =0; k < Conf->Enumerate("goodchan"); k++)
00060                                                 {
00061                                                         if (InspIRCd::Match(redirect, Conf->ReadValue("goodchan","name",k)))
00062                                                                 goodchan = true;
00063                                                 }
00064 
00065                                                 if (!goodchan)
00066                                                 {
00067                                                         /* <badchan:redirect> is a badchan */
00068                                                         if (user)
00069                                                                 user->WriteServ("NOTICE %s :Badchan %s redirects to badchan %s", user->nick.c_str(), name.c_str(), redirect.c_str());
00070                                                         throw ModuleException("Badchan redirect loop");
00071                                                 }
00072                                         }
00073                                 }
00074                         }
00075                 }
00076         }
00077 
00078         virtual ~ModuleDenyChannels()
00079         {
00080                 delete Conf;
00081         }
00082 
00083         virtual Version GetVersion()
00084         {
00085                 return Version("$Id: m_denychans.cpp 10339 2008-08-28 19:57:17Z w00t $", VF_VENDOR,API_VERSION);
00086         }
00087 
00088 
00089         virtual int OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
00090         {
00091                 for (int j =0; j < Conf->Enumerate("badchan"); j++)
00092                 {
00093                         if (InspIRCd::Match(cname, Conf->ReadValue("badchan","name",j)))
00094                         {
00095                                 if (IS_OPER(user) && Conf->ReadFlag("badchan","allowopers",j))
00096                                 {
00097                                         return 0;
00098                                 }
00099                                 else
00100                                 {
00101                                         std::string reason = Conf->ReadValue("badchan","reason",j);
00102                                         std::string redirect = Conf->ReadValue("badchan","redirect",j);
00103 
00104                                         for (int i = 0; i < Conf->Enumerate("goodchan"); i++)
00105                                         {
00106                                                 if (InspIRCd::Match(cname, Conf->ReadValue("goodchan", "name", i)))
00107                                                 {
00108                                                         return 0;
00109                                                 }
00110                                         }
00111 
00112                                         if (ServerInstance->IsChannel(redirect.c_str(), ServerInstance->Config->Limits.ChanMax))
00113                                         {
00114                                                 /* simple way to avoid potential loops: don't redirect to +L channels */
00115                                                 Channel *newchan = ServerInstance->FindChan(redirect);
00116                                                 if ((!newchan) || (!(newchan->IsModeSet('L'))))
00117                                                 {
00118                                                         user->WriteNumeric(926, "%s %s :Channel %s is forbidden, redirecting to %s: %s",user->nick.c_str(),cname,cname,redirect.c_str(), reason.c_str());
00119                                                         Channel::JoinUser(ServerInstance,user,redirect.c_str(),false,"",false,ServerInstance->Time());
00120                                                         return 1;
00121                                                 }
00122                                         }
00123 
00124                                         user->WriteNumeric(926, "%s %s :Channel %s is forbidden: %s",user->nick.c_str(),cname,cname,reason.c_str());
00125                                         return 1;
00126                                 }
00127                         }
00128                 }
00129                 return 0;
00130         }
00131 };
00132 
00133 MODULE_INIT(ModuleDenyChannels)