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_rline.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 "m_regex.h"
00016 #include "xline.h"
00017 
00018 static Module* rxengine = NULL;
00019 static Module* mymodule = NULL; /* Needed to let RLine send request! */
00020 
00021 /* $ModDesc: RLINE: Regexp user banning. */
00022 
00023 class RLine : public XLine
00024 {
00025  public:
00026 
00035         RLine(InspIRCd* Instance, time_t s_time, long d, const char* src, const char* re, const char* regexs) : XLine(Instance, s_time, d, src, re, "R")
00036         {
00037                 matchtext = regexs;
00038 
00039                 if (!rxengine)
00040                 {
00041                         ServerInstance->SNO->WriteToSnoMask('x', "Cannot create regexes until engine is set to a loaded provider!");
00042                         throw ModuleException("Regex engine not set or loaded!");
00043                 }
00044 
00045                 /* This can throw on failure, but if it does we DONT catch it here, we catch it and display it
00046                  * where the object is created, we might not ALWAYS want it to output stuff to snomask x all the time
00047                  */
00048                 regex = RegexFactoryRequest(mymodule, rxengine, regexs).Create();
00049         }
00050 
00053         ~RLine()
00054         {
00055                 delete regex;
00056         }
00057 
00058         bool Matches(User *u)
00059         {
00060                 std::string compare = u->nick + "!" + u->ident + "@" + u->host + " " + u->fullname;
00061                 return regex->Matches(compare);
00062         }
00063 
00064         bool Matches(const std::string &compare)
00065         {
00066                 return regex->Matches(compare);
00067         }
00068 
00069         void Apply(User* u)
00070         {
00071                 DefaultApply(u, "R", true);
00072         }
00073 
00074         void DisplayExpiry()
00075         {
00076                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed R-Line %s (set by %s %ld seconds ago)", this->matchtext.c_str(), this->source, this->duration);
00077         }
00078 
00079         const char* Displayable()
00080         {
00081                 return matchtext.c_str();
00082         }
00083 
00084         std::string matchtext;
00085 
00086         Regex *regex;
00087 };
00088 
00089 
00092 class RLineFactory : public XLineFactory
00093 {
00094  public:
00095         RLineFactory(InspIRCd* Instance) : XLineFactory(Instance, "R")
00096         {
00097         }
00098 
00101         XLine* Generate(time_t set_time, long duration, const char* source, const char* reason, const char* xline_specific_mask)
00102         {
00103                 return new RLine(ServerInstance, set_time, duration, source, reason, xline_specific_mask);
00104         }
00105 
00106         ~RLineFactory()
00107         {
00108         }
00109 };
00110 
00114 class CommandRLine : public Command
00115 {
00116         std::string rxengine;
00117 
00118  public:
00119         CommandRLine (InspIRCd* Instance) : Command(Instance,"RLINE", "o", 1, 3)
00120         {
00121                 this->source = "m_rline.so";
00122                 this->syntax = "<regex> [<rline-duration>] :<reason>";
00123         }
00124 
00125         CmdResult Handle (const std::vector<std::string>& parameters, User *user)
00126         {
00127 
00128                 if (parameters.size() >= 3)
00129                 {
00130                         // Adding - XXX todo make this respect <insane> tag perhaps..
00131 
00132                         long duration = ServerInstance->Duration(parameters[1]);
00133                         RLine *r = NULL;
00134 
00135                         try
00136                         {
00137                                 r = new RLine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
00138                         }
00139                         catch (ModuleException &e)
00140                         {
00141                                 ServerInstance->SNO->WriteToSnoMask('x',"Could not add RLINE: %s", e.GetReason());
00142                         }
00143 
00144                         if (r)
00145                         {
00146                                 if (ServerInstance->XLines->AddLine(r, user))
00147                                 {
00148                                         if (!duration)
00149                                         {
00150                                                 ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent R-Line for %s: %s", user->nick.c_str(), parameters[0].c_str(), parameters[2].c_str());
00151                                         }
00152                                         else
00153                                         {
00154                                                 time_t c_requires_crap = duration + ServerInstance->Time();
00155                                                 ServerInstance->SNO->WriteToSnoMask('x', "%s added timed R-Line for %s, expires on %s: %s", user->nick.c_str(), parameters[0].c_str(), ServerInstance->TimeString(c_requires_crap).c_str(), parameters[2].c_str());
00156                                         }
00157 
00158                                         ServerInstance->XLines->ApplyLines();
00159                                 }
00160                                 else
00161                                 {
00162                                         delete r;
00163                                         user->WriteServ("NOTICE %s :*** R-Line for %s already exists", user->nick.c_str(), parameters[0].c_str());
00164                                 }
00165                         }
00166                 }
00167                 else
00168                 {
00169                         if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "R", user))
00170                         {
00171                                 ServerInstance->SNO->WriteToSnoMask('x',"%s Removed R-Line on %s.",user->nick.c_str(),parameters[0].c_str());
00172                         }
00173                         else
00174                         {
00175                                 user->WriteServ("NOTICE %s :*** R-Line %s not found in list, try /stats R.",user->nick.c_str(),parameters[0].c_str());
00176                         }
00177                 }
00178 
00179                 return CMD_SUCCESS;
00180         }
00181 };
00182 
00183 class ModuleRLine : public Module
00184 {
00185  private:
00186         CommandRLine *r;
00187         RLineFactory *f;
00188         bool MatchOnNickChange;
00189         std::string RegexEngine;
00190 
00191  public:
00192         ModuleRLine(InspIRCd* Me) : Module(Me)
00193         {
00194                 mymodule = this;
00195                 OnRehash(NULL, "");
00196 
00197                 Me->Modules->UseInterface("RegularExpression");
00198 
00199                 // Create a new command
00200                 r = new CommandRLine(ServerInstance);
00201                 ServerInstance->AddCommand(r);
00202 
00203                 f = new RLineFactory(ServerInstance);
00204                 ServerInstance->XLines->RegisterFactory(f);
00205 
00206                 Implementation eventlist[] = { I_OnUserConnect, I_OnRehash, I_OnUserPostNick, I_OnLoadModule, I_OnStats };
00207                 ServerInstance->Modules->Attach(eventlist, this, 5);
00208 
00209         }
00210 
00211         virtual ~ModuleRLine()
00212         {
00213                 ServerInstance->Modules->DoneWithInterface("RegularExpression");
00214                 ServerInstance->XLines->DelAll("R");
00215                 ServerInstance->XLines->UnregisterFactory(f);
00216         }
00217 
00218         virtual Version GetVersion()
00219         {
00220                 return Version("$Id: m_rline.cpp 10741 2008-10-28 16:11:20Z w00t $", VF_COMMON | VF_VENDOR, API_VERSION);
00221         }
00222 
00223         virtual void OnUserConnect(User* user)
00224         {
00225                 // Apply lines on user connect
00226                 XLine *rl = ServerInstance->XLines->MatchesLine("R", user);
00227 
00228                 if (rl)
00229                 {
00230                         // Bang. :P
00231                         rl->Apply(user);
00232                 }
00233         }
00234 
00235         virtual void OnRehash(User *user, const std::string &parameter)
00236         {
00237                 ConfigReader Conf(ServerInstance);
00238 
00239                 MatchOnNickChange = Conf.ReadFlag("rline", "matchonnickchange", 0);
00240                 std::string newrxengine = Conf.ReadValue("rline", "engine", 0);
00241 
00242                 if (!RegexEngine.empty())
00243                 {
00244                         if (RegexEngine == newrxengine)
00245                                 return;
00246 
00247                         ServerInstance->SNO->WriteToSnoMask('x', "Dumping all R-Lines due to regex engine change (was '%s', now '%s')", RegexEngine.c_str(), newrxengine.c_str());
00248                         ServerInstance->XLines->DelAll("R");
00249                 }
00250                 rxengine = 0;
00251                 RegexEngine = newrxengine;
00252                 modulelist* ml = ServerInstance->Modules->FindInterface("RegularExpression");
00253                 if (ml)
00254                 {
00255                         for (modulelist::iterator i = ml->begin(); i != ml->end(); ++i)
00256                         {
00257                                 if (RegexNameRequest(this, *i).Send() == newrxengine)
00258                                 {
00259                                         ServerInstance->SNO->WriteToSnoMask('x', "R-Line now using engine '%s'", RegexEngine.c_str());
00260                                         rxengine = *i;
00261                                 }
00262                         }
00263                 }
00264                 if (!rxengine)
00265                 {
00266                         ServerInstance->SNO->WriteToSnoMask('x', "WARNING: Regex engine '%s' is not loaded - R-Line functionality disabled until this is corrected.", RegexEngine.c_str());
00267                 }
00268         }
00269 
00270         virtual int OnStats(char symbol, User* user, string_list &results)
00271         {
00272                 if (symbol != 'R')
00273                         return 0;
00274 
00275                 ServerInstance->XLines->InvokeStats("R", 223, user, results);
00276                 return 1;
00277         }
00278 
00279         virtual void OnLoadModule(Module* mod, const std::string& name)
00280         {
00281                 if (ServerInstance->Modules->ModuleHasInterface(mod, "RegularExpression"))
00282                 {
00283                         std::string rxname = RegexNameRequest(this, mod).Send();
00284                         if (rxname == RegexEngine)
00285                         {
00286                                 ServerInstance->SNO->WriteToSnoMask('x', "R-Line now using engine '%s'", RegexEngine.c_str());
00287                                 rxengine = mod;
00288                         }
00289                 }
00290         }
00291 
00292         virtual void OnUserPostNick(User *user, const std::string &oldnick)
00293         {
00294                 if (!IS_LOCAL(user))
00295                         return;
00296 
00297                 if (!MatchOnNickChange)
00298                         return;
00299 
00300                 XLine *rl = ServerInstance->XLines->MatchesLine("R", user);
00301 
00302                 if (rl)
00303                 {
00304                         // Bang! :D
00305                         rl->Apply(user);
00306                 }
00307         }
00308 
00309 };
00310 
00311 MODULE_INIT(ModuleRLine)
00312