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