* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- * E-mail:
- * <brain@chatspike.net>
- * <Craig@chatspike.net>
- *
- * Written by Craig Edwards, Craig McLure, and others.
+ * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
* This program is free but copyrighted software; see
* the file COPYING for details.
*
* ---------------------------------------------------
*/
-using namespace std;
-
#include <stdio.h>
#include <string>
#include <vector>
/* $ModDesc: Provides support for the /SILENCE command */
/* Improved drop-in replacement for the /SILENCE command
- * syntax: /SILENCE [+|-]<mask> <p|c|i|n|a|x> as in <private|channel|invites|notices|all|exclude>
+ * syntax: /SILENCE [+|-]<mask> <p|c|i|n|t|a|x> as in <privatemessage|channelmessage|invites|privatenotice|channelnotice|all|exclude>
*
* example that blocks all except private messages
* /SILENCE +*!*@* a
static int SILENCE_CHANNEL = 0x0002; /* c channel messages */
static int SILENCE_INVITE = 0x0004; /* i invites */
static int SILENCE_NOTICE = 0x0008; /* n notices */
-static int SILENCE_ALL = 0x0010; /* a all, (pcin) */
-static int SILENCE_EXCLUDE = 0x0020; /* x exclude this pattern */
+static int SILENCE_CNOTICE = 0x0010; /* t channel notices */
+static int SILENCE_ALL = 0x0020; /* a all, (pcint) */
+static int SILENCE_EXCLUDE = 0x0040; /* x exclude this pattern */
class cmd_silence : public command_t
cmd_silence (InspIRCd* Instance) : command_t(Instance,"SILENCE", 0, 0)
{
this->source = "m_silence_ext.so";
- syntax = "{[+|-]<mask> <p|c|i|n|a|x>}";
+ syntax = "{[+|-]<mask> <p|c|i|n|t|a|x>}";
}
CmdResult Handle (const char** parameters, int pcnt, userrec *user)
{
if (sl->size())
{
- silencelist::iterator i,safei;
- for (i = sl->begin(); i != sl->end(); i++)
+ for (silencelist::iterator i = sl->begin(); i != sl->end(); i++)
{
// search through for the item
irc::string listitem = i->first.c_str();
if (listitem == mask && i->second == pattern)
{
- safei = i;
- --i;
- sl->erase(safei);
+ sl->erase(i);
user->WriteServ("950 %s %s :Removed %s %s from silence list",user->nick, user->nick, mask.c_str(), DecompPattern(pattern).c_str());
break;
}
int CompilePattern(const char* pattern)
{
int p = 0;
- for (uint n = 0; n < strlen(pattern); n++)
+ for (const char* n = pattern; *n; n++)
{
- switch (pattern[n])
+ switch (*n)
{
case 'p':
p |= SILENCE_PRIVATE;
case 'n':
p |= SILENCE_NOTICE;
break;
+ case 't':
+ p |= SILENCE_CNOTICE;
+ break;
case 'a':
p |= SILENCE_ALL;
break;
/* turn the mask into a nice human readable format */
std::string DecompPattern (const int pattern)
{
- std::string out = "";
+ std::string out;
if ((pattern & SILENCE_PRIVATE) > 0)
- out += ",private";
+ out += ",privatemessages";
if ((pattern & SILENCE_CHANNEL) > 0)
- out += ",channel";
+ out += ",channelmessages";
if ((pattern & SILENCE_INVITE) > 0)
out += ",invites";
if ((pattern & SILENCE_NOTICE) > 0)
- out += ",notices";
+ out += ",privatenotices";
+ if ((pattern & SILENCE_CNOTICE) > 0)
+ out += ",channelnotices";
if ((pattern & SILENCE_ALL) > 0)
out = ",all";
if ((pattern & SILENCE_EXCLUDE) > 0)
void Implements(char* List)
{
- List[I_OnUserQuit] = List[I_On005Numeric] = List[I_OnUserPreNotice] = List[I_OnUserPreMessage] = 1;
- List[I_OnUserPreInvite] = 1;
- List[I_OnPreCommand] = 1;
+ List[I_OnBuildExemptList] = List[I_OnUserQuit] = List[I_On005Numeric] = List[I_OnUserPreNotice] = List[I_OnUserPreMessage] = List[I_OnUserPreInvite] = 1;
}
- virtual void OnUserQuit(userrec* user, const std::string &reason)
+ virtual void OnUserQuit(userrec* user, const std::string &reason, const std::string &oper_message)
{
// when the user quits tidy up any silence list they might have just to keep things tidy
- // and to prevent a HONKING BIG MEMORY LEAK!
silencelist* sl;
user->GetExt("silence_list", sl);
if (sl)
output = output + " ESILENCE SILENCE=999";
}
- virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text, char status)
+ virtual void OnBuildExemptList(MessageType message_type, chanrec* chan, userrec* sender, char status, CUList &exempt_list)
{
- if (target_type == TYPE_USER)
+ int public_silence = (message_type == MSG_PRIVMSG ? SILENCE_CHANNEL : SILENCE_CNOTICE);
+ CUList *ulist;
+ switch (status)
{
- return MatchPattern((userrec*)dest, user, SILENCE_PRIVATE);
+ case '@':
+ ulist = chan->GetOppedUsers();
+ break;
+ case '%':
+ ulist = chan->GetHalfoppedUsers();
+ break;
+ case '+':
+ ulist = chan->GetVoicedUsers();
+ break;
+ default:
+ ulist = chan->GetUsers();
+ break;
}
- return 0;
- }
-
- virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text, char status)
- {
- return MatchPattern((userrec*)dest, user, SILENCE_NOTICE);
- }
-
- virtual int OnUserPreInvite(userrec* source,userrec* dest,chanrec* channel)
- {
- return MatchPattern(dest, source, SILENCE_INVITE);
- }
- int MatchPattern(userrec* dest, userrec* source, int pattern)
- {
- silencelist* sl;
- dest->GetExt("silence_list", sl);
- if (sl)
+ for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
{
- for (silencelist::const_iterator c = sl->begin(); c != sl->end(); c++)
+ if (IS_LOCAL(i->second))
{
- if ((match(source->GetFullHost(), c->first.c_str())) && ( ((c->second & pattern) > 0)) || ((c->second & SILENCE_ALL) > 0))
+ if (MatchPattern(i->second, sender, public_silence) == 1)
{
- if (((c->second & SILENCE_EXCLUDE) > 0))
- {
- return 0;
- }
- else {
- return 1;
- }
+ exempt_list[i->second] = i->second;
}
}
}
- return 0;
}
- virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated, const std::string &original_line)
+ virtual int PreText(userrec* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list, int silence_type)
{
- /* Implement the part of cmd_privmsg.cpp that handles *channel* messages, if cmd_privmsg.cpp
- * is changed this probably needs updating too. Also implement the actual write to the users
- * on the channel. This code is from channels.cpp, and should also be changed if channels.cpp
- * updates it's corresponding code
- */
- if ((validated) && (command == "PRIVMSG"))
- {
- char status = 0;
- if ((*parameters[0] == '@') || (*parameters[0] == '%') || (*parameters[0] == '+'))
- {
- status = *parameters[0];
- parameters[0]++;
- }
- if (parameters[0][0] == '#')
- {
- chanrec *chan;
- user->idle_lastmsg = ServerInstance->Time();
- chan = ServerInstance->FindChan(parameters[0]);
- if (chan)
- {
- if (IS_LOCAL(user))
- {
- if ((chan->modes[CM_NOEXTERNAL]) && (!chan->HasUser(user)))
- {
- user->WriteServ("404 %s %s :Cannot send to channel (no external messages)", user->nick, chan->name);
- return 1;
- }
- if ((chan->modes[CM_MODERATED]) && (chan->GetStatus(user) < STATUS_VOICE))
- {
- user->WriteServ("404 %s %s :Cannot send to channel (+m)", user->nick, chan->name);
- return 1;
- }
- }
- int MOD_RESULT = 0;
-
- std::string temp = parameters[1];
- FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user,chan,TYPE_CHANNEL,temp,status));
- if (MOD_RESULT) {
- return 1;
- }
- parameters[1] = temp.c_str();
-
- if (temp == "")
- {
- user->WriteServ("412 %s No text to send", user->nick);
- return 1;
- }
+ if (!IS_LOCAL(user))
+ return 0;
- /* This next call into channel.cpp is the one that gets replaced by our modified method
- * chan->WriteAllExceptSender(user, false, status, "PRIVMSG %s :%s", chan->name, parameters[1]);
- */
- WriteAllExceptSenderAndSilenced(chan, user, false, status, "PRIVMSG %s :%s", chan->name, parameters[1]);
-
- FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,parameters[1],status));
- return 1;
- }
- else
- {
- /* no such nick/channel */
- user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[0]);
- return 1;
- }
- return 1;
- }
- else
+ if (target_type == TYPE_USER)
+ {
+ return MatchPattern((userrec*)dest, user, silence_type);
+ }
+ else if (target_type == TYPE_CHANNEL)
+ {
+ chanrec* chan = (chanrec*)dest;
+ if (chan)
{
- command_t* privmsg_command = ServerInstance->Parser->GetHandler("PRIVMSG");
- if (privmsg_command)
- {
- privmsg_command->Handle(parameters, pcnt, user);
- return 1;
- }
- else
- {
- ServerInstance->Log(DEBUG, "Could not find PRIVMSG Command!");
- }
+ this->OnBuildExemptList((silence_type == SILENCE_PRIVATE ? MSG_PRIVMSG : MSG_NOTICE), chan, user, status, exempt_list);
}
}
return 0;
}
- /* Taken from channels.cpp and slightly modified, see OnPreCommand above*/
- void WriteAllExceptSenderAndSilenced(chanrec* chan, userrec* user, bool serversource, char status, char* text, ...)
+ virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- if (!text)
- return;
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
+ return PreText(user, dest, target_type, text, status, exempt_list, SILENCE_PRIVATE);
+ }
- this->WriteAllExceptSenderAndSilenced(chan, user, serversource, status, std::string(textbuffer));
+ virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ {
+ return PreText(user, dest, target_type, text, status, exempt_list, SILENCE_NOTICE);
}
- /* Taken from channels.cpp and slightly modified, see OnPreCommand above*/
- void WriteAllExceptSenderAndSilenced(chanrec* chan, userrec* user, bool serversource, char status, const std::string& text)
+ virtual int OnUserPreInvite(userrec* source,userrec* dest,chanrec* channel)
{
- CUList *ulist;
+ return MatchPattern(dest, source, SILENCE_INVITE);
+ }
- switch (status)
- {
- case '@':
- ulist = chan->GetOppedUsers();
- break;
- case '%':
- ulist = chan->GetHalfoppedUsers();
- break;
- case '+':
- ulist = chan->GetVoicedUsers();
- break;
- default:
- ulist = chan->GetUsers();
- break;
- }
-
- for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
+ int MatchPattern(userrec* dest, userrec* source, int pattern)
+ {
+ silencelist* sl;
+ dest->GetExt("silence_list", sl);
+ if (sl)
{
- if ((IS_LOCAL(i->second)) && (user != i->second))
+ for (silencelist::const_iterator c = sl->begin(); c != sl->end(); c++)
{
- if (serversource)
- {
- i->second->WriteServ(text);
- }
- else
- {
- if (MatchPattern(i->second, user, SILENCE_CHANNEL) == 0)
- {
- i->second->WriteFrom(user,text);
- }
- }
+ if (((((c->second & pattern) > 0)) || ((c->second & SILENCE_ALL) > 0)) && (ServerInstance->MatchText(source->GetFullHost(), c->first)))
+ return !(((c->second & SILENCE_EXCLUDE) > 0));
}
}
+ return 0;
}
virtual ~ModuleSilence()