]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/core/m_mode.c
Change the DNSBL hit snomask to SNO_REJ (+r) as to not spam SNO_GENERAL
[irc/rqf/shadowircd.git] / modules / core / m_mode.c
CommitLineData
212380e3 1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_mode.c: Sets a user or channel mode.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
212380e3 24 */
25
26#include "stdinc.h"
212380e3 27#include "channel.h"
28#include "client.h"
29#include "hash.h"
13ae2f4b 30#include "match.h"
212380e3 31#include "ircd.h"
32#include "numeric.h"
33#include "s_user.h"
34#include "s_conf.h"
35#include "s_serv.h"
d3455e2c 36#include "logger.h"
212380e3 37#include "send.h"
38#include "msg.h"
39#include "parse.h"
40#include "modules.h"
41#include "packet.h"
212380e3 42#include "s_newconf.h"
43
44static int m_mode(struct Client *, struct Client *, int, const char **);
45static int ms_mode(struct Client *, struct Client *, int, const char **);
46static int ms_tmode(struct Client *, struct Client *, int, const char **);
47static int ms_bmask(struct Client *, struct Client *, int, const char **);
48
49struct Message mode_msgtab = {
50 "MODE", 0, 0, 0, MFLG_SLOW,
51 {mg_unreg, {m_mode, 2}, {m_mode, 3}, {ms_mode, 3}, mg_ignore, {m_mode, 2}}
52};
53struct Message tmode_msgtab = {
54 "TMODE", 0, 0, 0, MFLG_SLOW,
55 {mg_ignore, mg_ignore, {ms_tmode, 4}, {ms_tmode, 4}, mg_ignore, mg_ignore}
56};
57struct Message bmask_msgtab = {
58 "BMASK", 0, 0, 0, MFLG_SLOW,
59 {mg_ignore, mg_ignore, mg_ignore, {ms_bmask, 5}, mg_ignore, mg_ignore}
60};
61
62mapi_clist_av1 mode_clist[] = { &mode_msgtab, &tmode_msgtab, &bmask_msgtab, NULL };
63
64DECLARE_MODULE_AV1(mode, NULL, NULL, mode_clist, NULL, NULL, "$Revision: 1006 $");
65
66/*
67 * m_mode - MODE command handler
212380e3 68 * parv[1] - channel
69 */
70static int
71m_mode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
72{
73 struct Channel *chptr = NULL;
74 struct membership *msptr;
75 int n = 2;
76 const char *dest;
77 int operspy = 0;
78
79 dest = parv[1];
80
81 if(IsOperSpy(source_p) && *dest == '!')
82 {
83 dest++;
84 operspy = 1;
85
86 if(EmptyString(dest))
87 {
88 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
89 me.name, source_p->name, "MODE");
90 return 0;
91 }
92 }
93
94 /* Now, try to find the channel in question */
95 if(!IsChanPrefix(*dest))
96 {
97 /* if here, it has to be a non-channel name */
98 user_mode(client_p, source_p, parc, parv);
99 return 0;
100 }
101
102 if(!check_channel_name(dest))
103 {
104 sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[1]);
105 return 0;
106 }
107
108 chptr = find_channel(dest);
109
110 if(chptr == NULL)
111 {
112 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
113 form_str(ERR_NOSUCHCHANNEL), parv[1]);
114 return 0;
115 }
116
117 /* Now know the channel exists */
118 if(parc < n + 1)
119 {
120 if(operspy)
121 report_operspy(source_p, "MODE", chptr->chname);
122
123 sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
124 me.name, source_p->name, parv[1],
125 operspy ? channel_modes(chptr, &me) : channel_modes(chptr, source_p));
126
127 sendto_one(source_p, form_str(RPL_CREATIONTIME),
128 me.name, source_p->name, parv[1], chptr->channelts);
129 }
130 else
131 {
132 msptr = find_channel_membership(chptr, source_p);
133
212380e3 134 /* Finish the flood grace period... */
135 if(MyClient(source_p) && !IsFloodDone(source_p))
136 {
137 if(!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0')))
138 flood_endgrace(source_p);
139 }
140
141 set_channel_mode(client_p, source_p, chptr, msptr, parc - n, parv + n);
142 }
143
144 return 0;
145}
146
147static int
148ms_mode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
149{
150 struct Channel *chptr;
151
152 chptr = find_channel(parv[1]);
153
154 if(chptr == NULL)
155 {
156 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
157 form_str(ERR_NOSUCHCHANNEL), parv[1]);
158 return 0;
159 }
160
161 set_channel_mode(client_p, source_p, chptr, NULL, parc - 2, parv + 2);
162
163 return 0;
164}
165
166static int
167ms_tmode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
168{
169 struct Channel *chptr = NULL;
170 struct membership *msptr;
171
172 /* Now, try to find the channel in question */
173 if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
174 {
175 sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]);
176 return 0;
177 }
178
179 chptr = find_channel(parv[2]);
180
181 if(chptr == NULL)
182 {
183 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
184 form_str(ERR_NOSUCHCHANNEL), parv[2]);
185 return 0;
186 }
187
188 /* TS is higher, drop it. */
189 if(atol(parv[1]) > chptr->channelts)
190 return 0;
191
192 if(IsServer(source_p))
193 {
194 set_channel_mode(client_p, source_p, chptr, NULL, parc - 3, parv + 3);
195 }
196 else
197 {
198 msptr = find_channel_membership(chptr, source_p);
199
212380e3 200 set_channel_mode(client_p, source_p, chptr, msptr, parc - 3, parv + 3);
201 }
202
203 return 0;
204}
205
206static int
207ms_bmask(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
208{
209 static char modebuf[BUFSIZE];
210 static char parabuf[BUFSIZE];
211 struct Channel *chptr;
08d11e34 212 rb_dlink_list *banlist;
212380e3 213 const char *s;
214 char *t;
215 char *mbuf;
216 char *pbuf;
217 long mode_type;
218 int mlen;
219 int plen = 0;
220 int tlen;
221 int arglen;
222 int modecount = 0;
223 int needcap = NOCAPS;
224 int mems;
225 struct Client *fakesource_p;
226
227 if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
228 return 0;
229
230 if((chptr = find_channel(parv[2])) == NULL)
231 return 0;
232
233 /* TS is higher, drop it. */
234 if(atol(parv[1]) > chptr->channelts)
235 return 0;
236
237 switch (parv[3][0])
238 {
239 case 'b':
240 banlist = &chptr->banlist;
241 mode_type = CHFL_BAN;
242 mems = ALL_MEMBERS;
243 break;
244
245 case 'e':
246 banlist = &chptr->exceptlist;
247 mode_type = CHFL_EXCEPTION;
248 needcap = CAP_EX;
249 mems = ONLY_CHANOPS;
250 break;
251
252 case 'I':
253 banlist = &chptr->invexlist;
254 mode_type = CHFL_INVEX;
255 needcap = CAP_IE;
256 mems = ONLY_CHANOPS;
257 break;
258
259 case 'q':
260 banlist = &chptr->quietlist;
261 mode_type = CHFL_QUIET;
262 mems = ALL_MEMBERS;
263 break;
264
265 /* maybe we should just blindly propagate this? */
266 default:
267 return 0;
268 }
269
270 parabuf[0] = '\0';
271 s = LOCAL_COPY(parv[4]);
272
273 /* Hide connecting server on netburst -- jilles */
274 if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
275 fakesource_p = &me;
276 else
277 fakesource_p = source_p;
581fa5c4 278 mlen = rb_sprintf(modebuf, ":%s MODE %s +", fakesource_p->name, chptr->chname);
212380e3 279 mbuf = modebuf + mlen;
280 pbuf = parabuf;
281
282 while(*s == ' ')
283 s++;
284
285 /* next char isnt a space, point t to the next one */
286 if((t = strchr(s, ' ')) != NULL)
287 {
288 *t++ = '\0';
289
290 /* double spaces will break the parser */
291 while(*t == ' ')
292 t++;
293 }
294
295 /* couldve skipped spaces and got nothing.. */
296 while(!EmptyString(s))
297 {
298 /* ban with a leading ':' -- this will break the protocol */
299 if(*s == ':')
300 goto nextban;
301
302 tlen = strlen(s);
303
304 /* I dont even want to begin parsing this.. */
305 if(tlen > MODEBUFLEN)
306 break;
307
308 if(add_id(fakesource_p, chptr, s, banlist, mode_type))
309 {
310 /* this new one wont fit.. */
311 if(mlen + MAXMODEPARAMS + plen + tlen > BUFSIZE - 5 ||
312 modecount >= MAXMODEPARAMS)
313 {
314 *mbuf = '\0';
315 *(pbuf - 1) = '\0';
316 sendto_channel_local(mems, chptr, "%s %s", modebuf, parabuf);
317 sendto_server(client_p, chptr, needcap, CAP_TS6,
318 "%s %s", modebuf, parabuf);
319
320 mbuf = modebuf + mlen;
321 pbuf = parabuf;
322 plen = modecount = 0;
323 }
324
325 *mbuf++ = parv[3][0];
581fa5c4 326 arglen = rb_sprintf(pbuf, "%s ", s);
212380e3 327 pbuf += arglen;
328 plen += arglen;
329 modecount++;
330 }
331
332 nextban:
333 s = t;
334
335 if(s != NULL)
336 {
337 if((t = strchr(s, ' ')) != NULL)
338 {
339 *t++ = '\0';
340
341 while(*t == ' ')
342 t++;
343 }
344 }
345 }
346
347 if(modecount)
348 {
349 *mbuf = '\0';
350 *(pbuf - 1) = '\0';
351 sendto_channel_local(mems, chptr, "%s %s", modebuf, parabuf);
352 sendto_server(client_p, chptr, needcap, CAP_TS6, "%s %s", modebuf, parabuf);
353 }
354
355 sendto_server(client_p, chptr, CAP_TS6 | needcap, NOCAPS, ":%s BMASK %ld %s %s :%s",
356 source_p->id, (long) chptr->channelts, chptr->chname, parv[3], parv[4]);
357 return 0;
358}
359