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_blockcaps.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: Provides support to block all-CAPS channel messages and notices */
00017 
00018 
00021 class BlockCaps : public SimpleChannelModeHandler
00022 {
00023  public:
00024         BlockCaps(InspIRCd* Instance) : SimpleChannelModeHandler(Instance, 'B') { }
00025 };
00026 
00027 class ModuleBlockCAPS : public Module
00028 {
00029         BlockCaps* bc;
00030         int percent;
00031         unsigned int minlen;
00032         char capsmap[256];
00033 public:
00034 
00035         ModuleBlockCAPS(InspIRCd* Me) : Module(Me)
00036         {
00037                 OnRehash(NULL,"");
00038                 bc = new BlockCaps(ServerInstance);
00039                 if (!ServerInstance->Modes->AddMode(bc))
00040                 {
00041                         delete bc;
00042                         throw ModuleException("Could not add new modes!");
00043                 }
00044                 Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash, I_On005Numeric };
00045                 ServerInstance->Modules->Attach(eventlist, this, 4);
00046         }
00047 
00048         virtual void On005Numeric(std::string &output)
00049         {
00050                 ServerInstance->AddExtBanChar('B');
00051         }
00052 
00053         virtual void OnRehash(User* user, const std::string &param)
00054         {
00055                 ReadConf();
00056         }
00057 
00058         virtual int OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
00059         {
00060                 if (target_type == TYPE_CHANNEL)
00061                 {
00062                         if ((!IS_LOCAL(user)) || (text.length() < minlen))
00063                                 return 0;
00064 
00065                         Channel* c = (Channel*)dest;
00066 
00067                         if (CHANOPS_EXEMPT(ServerInstance, 'B') && c->GetStatus(user) == STATUS_OP)
00068                         {
00069                                 return 0;
00070                         }
00071 
00072                         if (c->IsModeSet('B') || c->IsExtBanned(user, 'B'))
00073                         {
00074                                 int caps = 0;
00075                                 const char* actstr = "\1ACTION ";
00076                                 int act = 0;
00077 
00078                                 for (std::string::iterator i = text.begin(); i != text.end(); i++)
00079                                 {
00080                                         /* Smart fix for suggestion from Jobe, ignore CTCP ACTION (part of /ME) */
00081                                         if (*actstr && *i == *actstr++ && act != -1)
00082                                         {
00083                                                 act++;
00084                                                 continue;
00085                                         }
00086                                         else
00087                                                 act = -1;
00088 
00089                                         caps += capsmap[(unsigned char)*i];
00090                                 }
00091                                 if ( ((caps*100)/(int)text.length()) >= percent )
00092                                 {
00093                                         user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s %s :Your line cannot be more than %d%% capital letters if it is %d or more letters long", user->nick.c_str(), c->name.c_str(), percent, minlen);
00094                                         return 1;
00095                                 }
00096                         }
00097                 }
00098                 return 0;
00099         }
00100 
00101         virtual int OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
00102         {
00103                 return OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
00104         }
00105 
00106         void ReadConf()
00107         {
00108                 ConfigReader Conf(ServerInstance);
00109                 percent = Conf.ReadInteger("blockcaps", "percent", "100", 0, true);
00110                 minlen = Conf.ReadInteger("blockcaps", "minlen", "1", 0, true);
00111                 std::string hmap = Conf.ReadValue("blockcaps", "capsmap", 0);
00112                 if (hmap.empty())
00113                         hmap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00114                 memset(capsmap, 0, sizeof(capsmap));
00115                 for (std::string::iterator n = hmap.begin(); n != hmap.end(); n++)
00116                         capsmap[(unsigned char)*n] = 1;
00117                 if (percent < 1 || percent > 100)
00118                 {
00119                         ServerInstance->Logs->Log("CONFIG",DEFAULT, "<blockcaps:percent> out of range, setting to default of 100.");
00120                         percent = 100;
00121                 }
00122                 if (minlen < 1 || minlen > MAXBUF-1)
00123                 {
00124                         ServerInstance->Logs->Log("CONFIG",DEFAULT, "<blockcaps:minlen> out of range, setting to default of 1.");
00125                         minlen = 1;
00126                 }
00127         }
00128 
00129         virtual ~ModuleBlockCAPS()
00130         {
00131                 ServerInstance->Modes->DelMode(bc);
00132                 delete bc;
00133         }
00134 
00135         virtual Version GetVersion()
00136         {
00137                 return Version("$Id: m_blockcaps.cpp 10291 2008-08-25 20:35:51Z w00t $", VF_COMMON|VF_VENDOR,API_VERSION);
00138         }
00139 };
00140 
00141 MODULE_INIT(ModuleBlockCAPS)