+bool FilterBase::AppliesToMe(User* user, FilterResult* filter, int iflags)
+{
+ if ((filter->flag_no_opers) && IS_OPER(user))
+ return false;
+ if ((iflags & FLAG_PRIVMSG) && (!filter->flag_privmsg))
+ return false;
+ if ((iflags & FLAG_NOTICE) && (!filter->flag_notice))
+ return false;
+ if ((iflags & FLAG_QUIT) && (!filter->flag_quit_message))
+ return false;
+ if ((iflags & FLAG_PART) && (!filter->flag_part_message))
+ return false;
+ return true;
+}
+
+FilterBase::FilterBase(InspIRCd* Me, const std::string &source) : Module(Me)
+{
+ Me->Modules->UseInterface("RegularExpression");
+ filtcommand = new CommandFilter(this, Me, source);
+ ServerInstance->AddCommand(filtcommand);
+ Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncOtherMetaData, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash, I_OnLoadModule };
+ ServerInstance->Modules->Attach(eventlist, this, 8);
+}
+
+FilterBase::~FilterBase()
+{
+ ServerInstance->Modules->DoneWithInterface("RegularExpression");
+}
+
+int FilterBase::OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+{
+ flags = FLAG_PRIVMSG;
+ return OnUserPreNotice(user,dest,target_type,text,status,exempt_list);
+}
+
+int FilterBase::OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+{
+ if (!flags)
+ flags = FLAG_NOTICE;
+
+ /* Leave ulines alone */
+ if ((ServerInstance->ULine(user->server)) || (!IS_LOCAL(user)))
+ return 0;
+
+ FilterResult* f = this->FilterMatch(user, text, flags);
+ if (f)
+ {
+ std::string target = "";
+ if (target_type == TYPE_USER)
+ {
+ User* t = (User*)dest;
+ target = std::string(t->nick);
+ }
+ else if (target_type == TYPE_CHANNEL)
+ {
+ Channel* t = (Channel*)dest;
+ target = std::string(t->name);
+ std::vector<std::string>::iterator i = find(exemptfromfilter.begin(), exemptfromfilter.end(), target);
+ if (i != exemptfromfilter.end()) return 0;
+ }
+ if (f->action == "block")
+ {
+ ServerInstance->SNO->WriteToSnoMask('A', std::string("FILTER: ")+user->nick+" had their message filtered, target was "+target+": "+f->reason);
+ user->WriteServ("NOTICE "+std::string(user->nick)+" :Your message has been filtered and opers notified: "+f->reason);
+ }
+ if (f->action == "silent")
+ {
+ user->WriteServ("NOTICE "+std::string(user->nick)+" :Your message has been filtered: "+f->reason);
+ }
+ if (f->action == "kill")
+ {
+ ServerInstance->Users->QuitUser(user, "Filtered: " + f->reason);
+ }
+ if (f->action == "gline")
+ {
+ GLine* gl = new GLine(ServerInstance, ServerInstance->Time(), f->gline_time, ServerInstance->Config->ServerName, f->reason.c_str(), "*", user->GetIPString());
+ if (ServerInstance->XLines->AddLine(gl,NULL))
+ {
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
+ delete gl;
+ }
+
+ ServerInstance->Logs->Log("FILTER",DEFAULT,"FILTER: "+ user->nick + " had their message filtered, target was " + target + ": " + f->reason + " Action: " + f->action);
+ return 1;
+ }
+ return 0;
+}
+
+int FilterBase::OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line)
+{
+ flags = 0;
+ if (validated && IS_LOCAL(user))
+ {
+ std::string checkline;
+ int replacepoint = 0;
+ bool parting = false;
+
+ if (command == "QUIT")
+ {
+ /* QUIT with no reason: nothing to do */
+ if (parameters.size() < 1)
+ return 0;
+
+ checkline = parameters[0];
+ replacepoint = 0;
+ parting = false;
+ flags = FLAG_QUIT;
+ }
+ else if (command == "PART")
+ {
+ /* PART with no reason: nothing to do */
+ if (parameters.size() < 2)
+ return 0;
+
+ std::vector<std::string>::iterator i = find(exemptfromfilter.begin(), exemptfromfilter.end(), parameters[0]);
+ if (i != exemptfromfilter.end()) return 0;
+ checkline = parameters[1];
+ replacepoint = 1;
+ parting = true;
+ flags = FLAG_PART;
+ }
+ else
+ /* We're only messing with PART and QUIT */
+ return 0;
+
+ FilterResult* f = NULL;
+
+ if (flags)
+ f = this->FilterMatch(user, checkline, flags);
+
+ if (!f)
+ /* PART or QUIT reason doesnt match a filter */
+ return 0;
+
+ /* We cant block a part or quit, so instead we change the reason to 'Reason filtered' */
+ Command* c = ServerInstance->Parser->GetHandler(command);
+ if (c)
+ {
+ std::vector<std::string> params;
+ for (int item = 0; item < (int)parameters.size(); item++)
+ params.push_back(parameters[item]);
+ params[replacepoint] = "Reason filtered";
+
+ /* We're blocking, OR theyre quitting and its a KILL action
+ * (we cant kill someone whos already quitting, so filter them anyway)
+ */
+ if ((f->action == "block") || (((!parting) && (f->action == "kill"))) || (f->action == "silent"))
+ {
+ c->Handle(params, user);
+ return 1;
+ }
+ else
+ {
+ /* Are they parting, if so, kill is applicable */
+ if ((parting) && (f->action == "kill"))