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_shun.cpp

Go to the documentation of this file.
00001 #include "inspircd.h"
00002 #include "xline.h"
00003 
00004 /* $ModDesc: Provides the /shun command, which stops a user executing all commands except PING and PONG. */
00005 
00006 class Shun : public XLine
00007 {
00008 public:
00009         std::string matchtext;
00010 
00011         Shun(InspIRCd* Instance, time_t s_time, long d, const char* src, const char* re, const char *shunmask) : XLine(Instance, s_time, d, src, re, "SHUN")
00012         {
00013                 this->matchtext = shunmask;
00014         }
00015 
00016         ~Shun()
00017         {
00018         }
00019 
00020         bool Matches(User *u)
00021         {
00022                 if (InspIRCd::Match(u->GetFullHost(), matchtext) || InspIRCd::Match(u->GetFullRealHost(), matchtext))
00023                         return true;
00024 
00025                 return false;
00026         }
00027 
00028         bool Matches(const std::string &s)
00029         {
00030                 if (matchtext == s)
00031                         return true;
00032                 return false;
00033         }
00034 
00035         void Apply(User *u)
00036         {
00037                 if (!u->GetExt("shunned"))
00038                         u->Extend("shunned");
00039         }
00040 
00041 
00042         void DisplayExpiry()
00043         {
00044                 ServerInstance->SNO->WriteToSnoMask('x',"Expiring timed shun %s (set by %s %ld seconds ago)", this->matchtext.c_str(), this->source, this->duration);
00045         }
00046 
00047         const char* Displayable()
00048         {
00049                 return matchtext.c_str();
00050         }
00051 };
00052 
00055 class ShunFactory : public XLineFactory
00056 {
00057  public:
00058         ShunFactory(InspIRCd* Instance) : XLineFactory(Instance, "SHUN") { }
00059 
00062         XLine* Generate(time_t set_time, long duration, const char* source, const char* reason, const char* xline_specific_mask)
00063         {
00064                 return new Shun(ServerInstance, set_time, duration, source, reason, xline_specific_mask);
00065         }
00066 };
00067 
00068 //typedef std::vector<Shun> shunlist;
00069 
00070 class cmd_shun : public Command
00071 {
00072  private:
00073         InspIRCd *Srv;
00074 
00075  public:
00076         cmd_shun(InspIRCd* Me) : Command(Me, "SHUN", "o", 1, 3), Srv(Me)
00077         {
00078                 this->source = "m_shun.so";
00079                 this->syntax = "<nick!user@hostmask> [<shun-duration>] :<reason>";
00080         }
00081 
00082         CmdResult Handle(const std::vector<std::string>& parameters, User *user)
00083         {
00084                 /* syntax: SHUN nick!user@host time :reason goes here */
00085                 /* 'time' is a human-readable timestring, like 2d3h2s. */
00086 
00087                 if (parameters.size() == 1)
00088                 {
00089                         if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "SHUN", user))
00090                         {
00091                                 ServerInstance->SNO->WriteToSnoMask('x',"%s Removed shun on %s.",user->nick.c_str(),parameters[0].c_str());
00092                         }
00093                         else
00094                         {
00095                                 // XXX todo implement stats
00096                                 user->WriteServ("NOTICE %s :*** Shun %s not found in list, try /stats s.",user->nick.c_str(),parameters[0].c_str());
00097                         }
00098 
00099                         return CMD_SUCCESS;
00100                 }
00101                 else if (parameters.size() >= 2)
00102                 {
00103                         // Adding - XXX todo make this respect <insane> tag perhaps..
00104                         long duration = ServerInstance->Duration(parameters[1]);
00105                         Shun *r = NULL;
00106 
00107                         try
00108                         {
00109                                 r = new Shun(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
00110                         }
00111                         catch (...)
00112                         {
00113                                 ; // Do nothing. If we get here, the regex was fucked up, and they already got told it fucked up.
00114                         }
00115 
00116                         if (r)
00117                         {
00118                                 if (ServerInstance->XLines->AddLine(r, user))
00119                                 {
00120                                         if (!duration)
00121                                         {
00122                                                 ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent shun for %s: %s", user->nick.c_str(), parameters[0].c_str(), parameters[2].c_str());
00123                                         }
00124                                         else
00125                                         {
00126                                                 time_t c_requires_crap = duration + ServerInstance->Time();
00127                                                 ServerInstance->SNO->WriteToSnoMask('x', "%s added timed shun 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());
00128                                         }
00129 
00130                                         ServerInstance->XLines->ApplyLines();
00131                                 }
00132                                 else
00133                                 {
00134                                         delete r;
00135                                         user->WriteServ("NOTICE %s :*** Shun for %s already exists", user->nick.c_str(), parameters[0].c_str());
00136                                 }
00137                         }
00138                 }
00139 
00140                 return CMD_FAILURE;
00141         }
00142 };
00143 
00144 class ModuleShun : public Module
00145 {
00146         cmd_shun* mycommand;
00147         ShunFactory *f;
00148         std::map<std::string, bool> ShunEnabledCommands;
00149         bool NotifyOfShun;
00150 
00151  public:
00152         ModuleShun(InspIRCd* Me) : Module(Me)
00153         {
00154                 f = new ShunFactory(ServerInstance);
00155                 ServerInstance->XLines->RegisterFactory(f);
00156 
00157                 mycommand = new cmd_shun(ServerInstance);
00158                 ServerInstance->AddCommand(mycommand);
00159 
00160                 Implementation eventlist[] = { I_OnStats, I_OnPreCommand, I_OnUserConnect, I_OnRehash };
00161                 ServerInstance->Modules->Attach(eventlist, this, 4);
00162                 OnRehash(NULL, "");
00163         }
00164 
00165         virtual ~ModuleShun()
00166         {
00167                 ServerInstance->XLines->DelAll("SHUN");
00168                 ServerInstance->XLines->UnregisterFactory(f);
00169         }
00170 
00171         virtual int OnStats(char symbol, User* user, string_list& out)
00172         {
00173                 if (symbol != 'S')
00174                         return 0;
00175 
00176                 ServerInstance->XLines->InvokeStats("SHUN", 223, user, out);
00177                 return 1;
00178         }
00179 
00180         virtual void OnRehash(User* user, const std::string &parameter)
00181         {
00182                 ConfigReader MyConf(ServerInstance);
00183                 std::string cmds = MyConf.ReadValue("shun", "enabledcommands", 0);
00184 
00185                 if (cmds.empty())
00186                         cmds = "PING PONG QUIT";
00187 
00188                 ShunEnabledCommands.clear();
00189                 NotifyOfShun = true;
00190 
00191                 std::stringstream dcmds(cmds);
00192                 std::string thiscmd;
00193 
00194                 while (dcmds >> thiscmd)
00195                 {
00196                         ShunEnabledCommands[thiscmd] = true;
00197                 }
00198 
00199                 NotifyOfShun = MyConf.ReadFlag("shun", "notifyuser", "yes", 0);
00200         }
00201 
00202         virtual void OnUserConnect(User* user)
00203         {
00204                 if (!IS_LOCAL(user))
00205                         return;
00206 
00207                 // Apply lines on user connect
00208                 XLine *rl = ServerInstance->XLines->MatchesLine("SHUN", user);
00209 
00210                 if (rl)
00211                 {
00212                         // Bang. :P
00213                         rl->Apply(user);
00214                 }
00215         }
00216 
00217         virtual int OnPreCommand(std::string &command, std::vector<std::string>& parameters, User* user, bool validated, const std::string &original_line)
00218         {
00219                 if (validated || !user->GetExt("shunned"))
00220                         return 0;
00221 
00222                 if (!ServerInstance->XLines->MatchesLine("SHUN", user))
00223                 {
00224                         /* The shun previously set on this user has expired or been removed */
00225                         user->Shrink("shunned");
00226                         return 0;
00227                 }
00228 
00229                 std::map<std::string, bool>::iterator i = ShunEnabledCommands.find(command);
00230 
00231                 if (i == ShunEnabledCommands.end())
00232                 {
00233                         user->WriteServ("NOTICE %s :*** Command %s not processed, as you have been blocked from issuing commands (SHUN)", user->nick.c_str(), command.c_str());
00234                         return 1;
00235                 }
00236 
00237                 if (command == "QUIT")
00238                 {
00239                         /* Allow QUIT but dont show any quit message */
00240                         parameters.clear();
00241                 }
00242                 else if (command == "PART")
00243                 {
00244                         /* same for PART */
00245                         parameters.clear();
00246                 }
00247 
00248                 return 1;
00249         }
00250 
00251         virtual Version GetVersion()
00252         {
00253                 return Version("$Id: m_shun.cpp 10741 2008-10-28 16:11:20Z w00t $",VF_VENDOR|VF_COMMON,API_VERSION);
00254         }
00255 };
00256 
00257 MODULE_INIT(ModuleShun)
00258