unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

silence.c (5812B)

      1 /*
      2  *   IRC - Internet Relay Chat, src/modules/silence.c
      3  *   (C) 2004- The UnrealIRCd Team
      4  *
      5  *   See file AUTHORS in IRC package for additional names of
      6  *   the programmers.
      7  *
      8  *   This program is free software; you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 1, or (at your option)
     11  *   any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *   GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program; if not, write to the Free Software
     20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     21  */
     22 
     23 #include "unrealircd.h"
     24 
     25 CMD_FUNC(cmd_silence);
     26 
     27 ModuleHeader MOD_HEADER
     28   = {
     29 	"silence",
     30 	"5.0",
     31 	"command /silence", 
     32 	"UnrealIRCd Team",
     33 	"unrealircd-6",
     34     };
     35 
     36 /* Structs */
     37 typedef struct Silence Silence;
     38 /** A /SILENCE entry */
     39 struct Silence
     40 {
     41 	Silence *prev, *next;
     42 	char mask[1]; /**< user!nick@host mask of silence entry */
     43 };
     44 
     45 /* Global variables */
     46 ModDataInfo *silence_md = NULL;
     47 
     48 /* Macros */
     49 #define SILENCELIST(x)       ((Silence *)moddata_local_client(x, silence_md).ptr)
     50 
     51 /* Forward declarations */
     52 int _is_silenced(Client *, Client *);
     53 int _del_silence(Client *client, const char *mask);
     54 int _add_silence(Client *client, const char *mask, int senderr);
     55 void silence_md_free(ModData *md);
     56 
     57 MOD_TEST()
     58 {
     59 	MARK_AS_OFFICIAL_MODULE(modinfo);
     60 	EfunctionAdd(modinfo->handle, EFUNC_ADD_SILENCE, _add_silence);
     61 	EfunctionAdd(modinfo->handle, EFUNC_DEL_SILENCE, _del_silence);
     62 	EfunctionAdd(modinfo->handle, EFUNC_IS_SILENCED, _is_silenced);
     63 	return MOD_SUCCESS;
     64 }
     65 
     66 MOD_INIT()
     67 {
     68 	ModDataInfo mreq;
     69 
     70 	MARK_AS_OFFICIAL_MODULE(modinfo);
     71 
     72 	memset(&mreq, 0, sizeof(mreq));
     73 	mreq.name = "silence";
     74 	mreq.type = MODDATATYPE_LOCAL_CLIENT;
     75 	mreq.free = silence_md_free;
     76 	silence_md = ModDataAdd(modinfo->handle, mreq);
     77 	if (!silence_md)
     78 	{
     79 		config_error("could not register silence moddata");
     80 		return MOD_FAILED;
     81 	}
     82 	CommandAdd(modinfo->handle, "SILENCE", cmd_silence, MAXPARA, CMD_USER);
     83 	return MOD_SUCCESS;
     84 }
     85 
     86 MOD_LOAD()
     87 {
     88 	return MOD_SUCCESS;
     89 }
     90 
     91 MOD_UNLOAD()
     92 {
     93 	return MOD_SUCCESS;
     94 }
     95 
     96 /** The /SILENCE command - server-side ignore list.
     97  * Syntax:
     98  * SILENCE +user  To add a user from the silence list
     99  * SILENCE -user  To remove a user from the silence list
    100  * SILENCE        To send the current silence list
    101  *
    102  */
    103 
    104 CMD_FUNC(cmd_silence)
    105 {
    106 	Silence *s;
    107 	const char *p;
    108 	char action;
    109 
    110 	if (MyUser(client))
    111 	{
    112 		if (parc < 2 || BadPtr(parv[1]))
    113 		{
    114 			for (s = SILENCELIST(client); s; s = s->next)
    115 				sendnumeric(client, RPL_SILELIST, s->mask);
    116 			sendnumeric(client, RPL_ENDOFSILELIST);
    117 			return;
    118 		}
    119 		p = parv[1];
    120 		action = *p;
    121 		if (action == '-' || action == '+')
    122 		{
    123 			p++;
    124 		} else
    125 		if (!strchr(p, '@') && !strchr(p, '.') && !strchr(p, '!') && !strchr(p, '*') && !find_user(p, NULL))
    126 		{
    127 			sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
    128 			return;
    129 		} else
    130 		{
    131 			action = '+';
    132 		}
    133 		p = pretty_mask(p);
    134 		if ((action == '-' && del_silence(client, p)) ||
    135 		    (action != '-' && add_silence(client, p, 1)))
    136 		{
    137 			sendto_prefix_one(client, client, NULL, ":%s SILENCE %c%s",
    138 			    client->name, action, p);
    139 		}
    140 		return;
    141 	}
    142 
    143 	/* Probably server to server traffic.
    144 	 * We don't care about this anymore on UnrealIRCd 5 and later.
    145 	 */
    146 }
    147 
    148 /** Delete item from the silence list.
    149  * @param client The client.
    150  * @param mask The mask to delete from the list.
    151  * @returns 1 if entry was found and deleted, 0 if not found.
    152  */
    153 int _del_silence(Client *client, const char *mask)
    154 {
    155 	Silence *s;
    156 
    157 	for (s = SILENCELIST(client); s; s = s->next)
    158 	{
    159 		if (mycmp(mask, s->mask) == 0)
    160 		{
    161 			DelListItemUnchecked(s, moddata_local_client(client, silence_md).ptr);
    162 			safe_free(s);
    163 			return 1;
    164 		}
    165 	}
    166 	return 0;
    167 }
    168 
    169 /** Add item to the silence list.
    170  * @param client The client.
    171  * @param mask The mask to add to the list.
    172  * @returns 1 if silence entry added,
    173  *          0 if not added, eg: full or already covered by an existing silence entry.
    174  */
    175 int _add_silence(Client *client, const char *mask, int senderr)
    176 {
    177 	Silence *s;
    178 	int cnt = 0;
    179 
    180 	if (!MyUser(client))
    181 		return 0;
    182 
    183 	for (s = SILENCELIST(client); s; s = s->next)
    184 	{
    185 		if ((strlen(s->mask) > MAXSILELENGTH) || (++cnt >= SILENCE_LIMIT))
    186 		{
    187 			if (senderr)
    188 				sendnumeric(client, ERR_SILELISTFULL, mask);
    189 			return 0;
    190 		}
    191 		else
    192 		{
    193 			if (match_simple(s->mask, mask))
    194 				return 0;
    195 		}
    196 	}
    197 
    198 	/* Add the new entry */
    199 	s = safe_alloc(sizeof(Silence)+strlen(mask));
    200 	strcpy(s->mask, mask); /* safe, allocated above */
    201 	AddListItemUnchecked(s, moddata_local_client(client, silence_md).ptr);
    202 	return 1;
    203 }
    204 
    205 /** Check whether sender is silenced by receiver.
    206  * @param sender    The client that intends to send a message.
    207  * @param receiver  The client that would receive the message.
    208  * @returns 1 if sender is silenced by receiver (do NOT send the message),
    209  *          0 if not silenced (go ahead and send).
    210  */
    211 int _is_silenced(Client *sender, Client *receiver)
    212 {
    213 	Silence *s;
    214 	char mask[HOSTLEN + NICKLEN + USERLEN + 5];
    215 
    216 	if (!MyUser(receiver) || !receiver->user || !sender->user || !SILENCELIST(receiver))
    217 		return 0;
    218 
    219 	ircsnprintf(mask, sizeof(mask), "%s!%s@%s", sender->name, sender->user->username, GetHost(sender));
    220 
    221 	for (s = SILENCELIST(receiver); s; s = s->next)
    222 	{
    223 		if (match_simple(s->mask, mask))
    224 			return 1;
    225 	}
    226 
    227 	return 0;
    228 }
    229 
    230 /** Called on client exit: free the silence list of this user */
    231 void silence_md_free(ModData *md)
    232 {
    233 	Silence *b, *b_next;
    234 
    235 	for (b = md->ptr; b; b = b_next)
    236 	{
    237 		b_next = b->next;
    238 		safe_free(b);
    239 	}
    240 	md->ptr = NULL;
    241 }