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 }