]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/core/m_sjoin.c
start making this compile
[irc/rqf/shadowircd.git] / modules / core / m_sjoin.c
CommitLineData
212380e3 1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_sjoin.c: Joins a user to a channel.
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 *
1117fbd3 24 * $Id: m_sjoin.c 3434 2007-04-28 23:47:25Z jilles $
212380e3 25 */
26
27#include "stdinc.h"
28#include "tools.h"
29#include "channel.h"
30#include "client.h"
31#include "hash.h"
32#include "irc_string.h"
33#include "sprintf_irc.h"
34#include "ircd.h"
35#include "numeric.h"
36#include "send.h"
37#include "common.h"
38#include "msg.h"
39#include "parse.h"
40#include "modules.h"
41#include "s_serv.h"
42#include "s_conf.h"
43
44static int ms_sjoin(struct Client *, struct Client *, int, const char **);
45
46struct Message sjoin_msgtab = {
47 "SJOIN", 0, 0, 0, MFLG_SLOW,
48 {mg_unreg, mg_ignore, mg_ignore, {ms_sjoin, 0}, mg_ignore, mg_ignore}
49};
50
51mapi_clist_av1 sjoin_clist[] = { &sjoin_msgtab, NULL };
52
1117fbd3 53DECLARE_MODULE_AV1(sjoin, NULL, NULL, sjoin_clist, NULL, NULL, "$Revision: 3434 $");
212380e3 54
55/*
56 * ms_sjoin
57 * parv[0] - sender
58 * parv[1] - TS
59 * parv[2] - channel
60 * parv[3] - modes + n arguments (key and/or limit)
61 * parv[4+n] - flags+nick list (all in one parameter)
62 *
63 * process a SJOIN, taking the TS's into account to either ignore the
64 * incoming modes or undo the existing ones or merge them, and JOIN
65 * all the specified users while sending JOIN/MODEs to local clients
66 */
67
68
69static char modebuf[MODEBUFLEN];
70static char parabuf[MODEBUFLEN];
71static const char *para[MAXMODEPARAMS];
72static char *mbuf;
73static int pargs;
74
75static void set_final_mode(struct Mode *mode, struct Mode *oldmode);
76static void remove_our_modes(struct Channel *chptr, struct Client *source_p);
77static void remove_ban_list(struct Channel *chptr, struct Client *source_p,
08d11e34 78 rb_dlink_list * list, char c, int cap, int mems);
212380e3 79
80static int
81ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
82{
83 static char buf_nick[BUFSIZE];
84 static char buf_uid[BUFSIZE];
85 static const char empty_modes[] = "0";
86 struct Channel *chptr;
87 struct Client *target_p, *fakesource_p;
88 time_t newts;
89 time_t oldts;
90 static struct Mode mode, *oldmode;
91 const char *modes;
92 int args = 0;
93 int keep_our_modes = 1;
94 int keep_new_modes = 1;
95 int fl;
96 int isnew;
97 int mlen_nick, mlen_uid;
98 int len_nick;
99 int len_uid;
100 int len;
101 int joins = 0;
102 const char *s;
103 char *ptr_nick;
104 char *ptr_uid;
105 char *p;
106 int i, joinc = 0, timeslice = 0;
107 static char empty[] = "";
08d11e34 108 rb_dlink_node *ptr, *next_ptr;
212380e3 109
110 if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
111 return 0;
112
113 /* SJOIN's for local channels can't happen. */
114 if(*parv[2] == '&')
115 return 0;
116
117 modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
118 pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
119
120 /* Hide connecting server on netburst -- jilles */
121 if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
122 fakesource_p = &me;
123 else
124 fakesource_p = source_p;
125
126 mbuf = modebuf;
127 newts = atol(parv[1]);
128
129 s = parv[3];
130 while (*s)
131 {
132 switch (*(s++))
133 {
134 case 'i':
135 mode.mode |= MODE_INVITEONLY;
136 break;
137 case 'n':
138 mode.mode |= MODE_NOPRIVMSGS;
139 break;
140 case 'p':
141 mode.mode |= MODE_PRIVATE;
142 break;
143 case 's':
144 mode.mode |= MODE_SECRET;
145 break;
146 case 'm':
147 mode.mode |= MODE_MODERATED;
148 break;
149 case 't':
150 mode.mode |= MODE_TOPICLIMIT;
151 break;
152 case 'r':
153 mode.mode |= MODE_REGONLY;
154 break;
155 case 'L':
156 mode.mode |= MODE_EXLIMIT;
157 break;
158 case 'P':
159 mode.mode |= MODE_PERMANENT;
160 break;
161 case 'c':
162 mode.mode |= MODE_NOCOLOR;
163 break;
164 case 'g':
165 mode.mode |= MODE_FREEINVITE;
166 break;
167 case 'z':
168 mode.mode |= MODE_OPMODERATE;
169 break;
170 case 'F':
171 mode.mode |= MODE_FREETARGET;
172 break;
173 case 'Q':
174 mode.mode |= MODE_DISFORWARD;
175 break;
176 case 'f':
177 strlcpy(mode.forward, parv[4 + args], sizeof(mode.forward));
178 args++;
179 if(parc < 5 + args)
180 return 0;
181 break;
182 case 'j':
183 sscanf(parv[4 + args], "%d:%d", &joinc, &timeslice);
184 args++;
185 mode.join_num = joinc;
186 mode.join_time = timeslice;
187 if(parc < 5 + args)
188 return 0;
189 break;
190 case 'k':
191 strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
192 args++;
193 if(parc < 5 + args)
194 return 0;
195 break;
196 case 'l':
197 mode.limit = atoi(parv[4 + args]);
198 args++;
199 if(parc < 5 + args)
200 return 0;
201 break;
202 }
203 }
204
205 if(parv[args + 4])
206 {
207 s = parv[args + 4];
208
209 /* remove any leading spaces */
210 while (*s == ' ')
211 s++;
212 }
213 else
214 s = "";
215
216 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
217 return 0; /* channel name too long? */
218
219
220 oldts = chptr->channelts;
221 oldmode = &chptr->mode;
222
223#ifdef IGNORE_BOGUS_TS
224 if(newts < 800000000)
225 {
226 sendto_realops_snomask(SNO_DEBUG, L_ALL,
227 "*** Bogus TS %ld on %s ignored from %s",
228 (long) newts, chptr->chname, client_p->name);
229
230 newts = (oldts == 0) ? oldts : 800000000;
231 }
232#else
233 if(!isnew && !newts && oldts)
234 {
235 sendto_channel_local(ALL_MEMBERS, chptr,
236 ":%s NOTICE %s :*** Notice -- TS for %s "
237 "changed from %ld to 0",
238 me.name, chptr->chname, chptr->chname, (long) oldts);
239 sendto_realops_snomask(SNO_GENERAL, L_ALL,
240 "Server %s changing TS on %s from %ld to 0",
241 source_p->name, chptr->chname, (long) oldts);
242 }
243#endif
244
245 if(isnew)
246 chptr->channelts = newts;
247
248 else if(newts == 0 || oldts == 0)
249 chptr->channelts = 0;
250 else if(newts == oldts)
251 ;
252 else if(newts < oldts)
253 {
254 /* If configured, kick people trying to join +i/+k
255 * channels by recreating them on split servers.
256 * Don't kick if the source has sent EOB (services
257 * deopping everyone by TS-1 SJOIN).
258 * -- jilles */
259 if (ConfigChannel.kick_on_split_riding &&
260 !HasSentEob(source_p) &&
261 ((mode.mode & MODE_INVITEONLY) ||
262 (mode.key[0] != 0 && irccmp(mode.key, oldmode->key) != 0)))
263 {
264 struct membership *msptr;
265 struct Client *who;
08d11e34
WP
266 int l = rb_dlink_list_length(&chptr->members);
267 int b = rb_dlink_list_length(&chptr->banlist) +
268 rb_dlink_list_length(&chptr->exceptlist) +
269 rb_dlink_list_length(&chptr->invexlist) +
270 rb_dlink_list_length(&chptr->quietlist);
212380e3 271
08d11e34 272 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
212380e3 273 {
274 msptr = ptr->data;
275 who = msptr->client_p;
276 sendto_one(who, ":%s KICK %s %s :Net Rider",
277 me.name, chptr->chname, who->name);
278
279 sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
280 ":%s KICK %s %s :Net Rider",
281 me.id, chptr->chname,
282 who->id);
283 sendto_server(NULL, chptr, NOCAPS, CAP_TS6,
284 ":%s KICK %s %s :Net Rider",
285 me.name, chptr->chname, who->name);
286 remove_user_from_channel(msptr);
287 if (--l == 0)
288 break;
289 }
290 if (l == 0)
291 {
292 /* Channel was emptied, create a new one */
293 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
294 return 0; /* oops! */
295
296 /* If the source does not do TS6,
297 * nontimestamped bans have been sent to it,
298 * but we have just lost those here. Let's
299 * warn the channel about this. Because
300 * of the kicks, any users on the channel
301 * will be at client_p. -- jilles */
302 if (!has_id(source_p) && b > 0)
303 sendto_one(client_p, ":%s NOTICE %s :*** Notice -- possible ban desync on %s, please remove any bans just added by servers", get_id(&me, client_p), parv[2], parv[2]);
304 oldmode = &chptr->mode;
305 }
306 }
307 keep_our_modes = NO;
308 chptr->channelts = newts;
309 }
310 else
311 keep_new_modes = NO;
312
313 if(!keep_new_modes)
314 mode = *oldmode;
315 else if(keep_our_modes)
316 {
317 mode.mode |= oldmode->mode;
318 if(oldmode->limit > mode.limit)
319 mode.limit = oldmode->limit;
320 if(strcmp(mode.key, oldmode->key) < 0)
321 strcpy(mode.key, oldmode->key);
322 if(oldmode->join_num > mode.join_num ||
323 (oldmode->join_num == mode.join_num &&
324 oldmode->join_time > mode.join_time))
325 {
326 mode.join_num = oldmode->join_num;
327 mode.join_time = oldmode->join_time;
328 }
329 if(irccmp(mode.forward, oldmode->forward) < 0)
330 strcpy(mode.forward, oldmode->forward);
331 }
332 else
333 {
334 /* If setting -j, clear join throttle state -- jilles */
335 if (!mode.join_num)
336 chptr->join_count = chptr->join_delta = 0;
337 }
338
339 set_final_mode(&mode, oldmode);
340 chptr->mode = mode;
341
342 /* Lost the TS, other side wins, so remove modes on this side */
343 if(!keep_our_modes)
344 {
345 remove_our_modes(chptr, fakesource_p);
08d11e34 346 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
212380e3 347 {
348 del_invite(chptr, ptr->data);
349 }
350 sendto_channel_local(ALL_MEMBERS, chptr,
351 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
352 me.name, chptr->chname, chptr->chname,
353 (long) oldts, (long) newts);
1117fbd3 354 /* Update capitalization in channel name, this makes the
355 * capitalization timestamped like modes are -- jilles */
356 strcpy(chptr->chname, parv[2]);
212380e3 357 }
358
359 if(*modebuf != '\0')
360 sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
361 fakesource_p->name, chptr->chname, modebuf, parabuf);
362
363 *modebuf = *parabuf = '\0';
364
365 if(parv[3][0] != '0' && keep_new_modes)
366 modes = channel_modes(chptr, source_p);
367 else
368 modes = empty_modes;
369
370 mlen_nick = ircsprintf(buf_nick, ":%s SJOIN %ld %s %s :",
371 source_p->name, (long) chptr->channelts, parv[2], modes);
372 ptr_nick = buf_nick + mlen_nick;
373
374 /* working on the presumption eventually itll be more efficient to
375 * build a TS6 buffer without checking its needed..
376 */
377 mlen_uid = ircsprintf(buf_uid, ":%s SJOIN %ld %s %s :",
378 use_id(source_p), (long) chptr->channelts, parv[2], modes);
379 ptr_uid = buf_uid + mlen_uid;
380
381 mbuf = modebuf;
382 para[0] = para[1] = para[2] = para[3] = empty;
383 pargs = 0;
384 len_nick = len_uid = 0;
385
386 /* if theres a space, theres going to be more than one nick, change the
387 * first space to \0, so s is just the first nick, and point p to the
388 * second nick
389 */
390 if((p = strchr(s, ' ')) != NULL)
391 {
392 *p++ = '\0';
393 }
394
395 *mbuf++ = '+';
396
397 while (s)
398 {
399 fl = 0;
400
401 for (i = 0; i < 2; i++)
402 {
403 if(*s == '@')
404 {
405 fl |= CHFL_CHANOP;
406 s++;
407 }
408 else if(*s == '+')
409 {
410 fl |= CHFL_VOICE;
411 s++;
412 }
413 }
414
415 /* if the client doesnt exist or is fake direction, skip. */
416 if(!(target_p = find_client(s)) ||
417 (target_p->from != client_p) || !IsPerson(target_p))
418 goto nextnick;
419
420 /* we assume for these we can fit at least one nick/uid in.. */
421
422 /* check we can fit another status+nick+space into a buffer */
423 if((mlen_nick + len_nick + NICKLEN + 3) > (BUFSIZE - 3))
424 {
425 *(ptr_nick - 1) = '\0';
426 sendto_server(client_p->from, NULL, NOCAPS, CAP_TS6, "%s", buf_nick);
427 ptr_nick = buf_nick + mlen_nick;
428 len_nick = 0;
429 }
430
431 if((mlen_uid + len_uid + IDLEN + 3) > (BUFSIZE - 3))
432 {
433 *(ptr_uid - 1) = '\0';
434 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
435 ptr_uid = buf_uid + mlen_uid;
436 len_uid = 0;
437 }
438
439 if(keep_new_modes)
440 {
441 if(fl & CHFL_CHANOP)
442 {
443 *ptr_nick++ = '@';
444 *ptr_uid++ = '@';
445 len_nick++;
446 len_uid++;
447 }
448 if(fl & CHFL_VOICE)
449 {
450 *ptr_nick++ = '+';
451 *ptr_uid++ = '+';
452 len_nick++;
453 len_uid++;
454 }
455 }
456
457 /* copy the nick to the two buffers */
458 len = ircsprintf(ptr_nick, "%s ", target_p->name);
459 ptr_nick += len;
460 len_nick += len;
461 len = ircsprintf(ptr_uid, "%s ", use_id(target_p));
462 ptr_uid += len;
463 len_uid += len;
464
465 if(!keep_new_modes)
fda6c724 466 fl = 0;
212380e3 467
468 if(!IsMember(target_p, chptr))
469 {
470 add_user_to_channel(chptr, target_p, fl);
471 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
472 target_p->name,
473 target_p->username, target_p->host, parv[2]);
474 joins++;
475 }
476
477 if(fl & CHFL_CHANOP)
478 {
479 *mbuf++ = 'o';
480 para[pargs++] = target_p->name;
481
482 /* a +ov user.. bleh */
483 if(fl & CHFL_VOICE)
484 {
485 /* its possible the +o has filled up MAXMODEPARAMS, if so, start
486 * a new buffer
487 */
488 if(pargs >= MAXMODEPARAMS)
489 {
490 *mbuf = '\0';
491 sendto_channel_local(ALL_MEMBERS, chptr,
492 ":%s MODE %s %s %s %s %s %s",
493 fakesource_p->name, chptr->chname,
494 modebuf,
495 para[0], para[1], para[2], para[3]);
496 mbuf = modebuf;
497 *mbuf++ = '+';
498 para[0] = para[1] = para[2] = para[3] = NULL;
499 pargs = 0;
500 }
501
502 *mbuf++ = 'v';
503 para[pargs++] = target_p->name;
504 }
505 }
506 else if(fl & CHFL_VOICE)
507 {
508 *mbuf++ = 'v';
509 para[pargs++] = target_p->name;
510 }
511
512 if(pargs >= MAXMODEPARAMS)
513 {
514 *mbuf = '\0';
515 sendto_channel_local(ALL_MEMBERS, chptr,
516 ":%s MODE %s %s %s %s %s %s",
517 fakesource_p->name,
518 chptr->chname,
519 modebuf, para[0], para[1], para[2], para[3]);
520 mbuf = modebuf;
521 *mbuf++ = '+';
522 para[0] = para[1] = para[2] = para[3] = NULL;
523 pargs = 0;
524 }
525
526 nextnick:
527 /* p points to the next nick */
528 s = p;
529
530 /* if there was a trailing space and p was pointing to it, then we
531 * need to exit.. this has the side effect of breaking double spaces
532 * in an sjoin.. but that shouldnt happen anyway
533 */
534 if(s && (*s == '\0'))
535 s = p = NULL;
536
537 /* if p was NULL due to no spaces, s wont exist due to the above, so
538 * we cant check it for spaces.. if there are no spaces, then when
539 * we next get here, s will be NULL
540 */
541 if(s && ((p = strchr(s, ' ')) != NULL))
542 {
543 *p++ = '\0';
544 }
545 }
546
547 *mbuf = '\0';
548 if(pargs)
549 {
550 sendto_channel_local(ALL_MEMBERS, chptr,
551 ":%s MODE %s %s %s %s %s %s",
552 fakesource_p->name, chptr->chname, modebuf,
553 para[0], CheckEmpty(para[1]),
554 CheckEmpty(para[2]), CheckEmpty(para[3]));
555 }
556
7201bb21 557 if(!joins && !(chptr->mode.mode & MODE_PERMANENT) && isnew)
212380e3 558 {
7201bb21 559 destroy_channel(chptr);
212380e3 560
561 return 0;
562 }
563
564 /* Keep the colon if we're sending an SJOIN without nicks -- jilles */
565 if (joins)
566 {
567 *(ptr_nick - 1) = '\0';
568 *(ptr_uid - 1) = '\0';
569 }
570
571 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
572 sendto_server(client_p->from, NULL, NOCAPS, CAP_TS6, "%s", buf_nick);
573
574 /* if the source does TS6 we have to remove our bans. Its now safe
575 * to issue -b's to the non-ts6 servers, as the sjoin we've just
576 * sent will kill any ops they have.
577 */
578 if(!keep_our_modes && source_p->id[0] != '\0')
579 {
08d11e34 580 if(rb_dlink_list_length(&chptr->banlist) > 0)
212380e3 581 remove_ban_list(chptr, fakesource_p, &chptr->banlist, 'b', NOCAPS, ALL_MEMBERS);
582
08d11e34 583 if(rb_dlink_list_length(&chptr->exceptlist) > 0)
212380e3 584 remove_ban_list(chptr, fakesource_p, &chptr->exceptlist,
585 'e', CAP_EX, ONLY_CHANOPS);
586
08d11e34 587 if(rb_dlink_list_length(&chptr->invexlist) > 0)
212380e3 588 remove_ban_list(chptr, fakesource_p, &chptr->invexlist,
589 'I', CAP_IE, ONLY_CHANOPS);
590
08d11e34 591 if(rb_dlink_list_length(&chptr->quietlist) > 0)
212380e3 592 remove_ban_list(chptr, fakesource_p, &chptr->quietlist,
593 'q', NOCAPS, ALL_MEMBERS);
594
595 chptr->bants++;
596 }
597
598 return 0;
599}
600
212380e3 601static void
602set_final_mode(struct Mode *mode, struct Mode *oldmode)
603{
604 int dir = MODE_QUERY;
605 char *pbuf = parabuf;
606 int len;
607 int i;
608
609 /* ok, first get a list of modes we need to add */
2a719c44 610 for (i = 0; chmode_flags[i].letter; i++)
212380e3 611 {
2a719c44 612 if((mode->mode & chmode_flags[i].mode) && !(oldmode->mode & chmode_flags[i].mode))
212380e3 613 {
614 if(dir != MODE_ADD)
615 {
616 *mbuf++ = '+';
617 dir = MODE_ADD;
618 }
2a719c44 619 *mbuf++ = chmode_flags[i].letter;
212380e3 620 }
621 }
622
623 /* now the ones we need to remove. */
2a719c44 624 for (i = 0; chmode_flags[i].letter; i++)
212380e3 625 {
2a719c44 626 if((oldmode->mode & chmode_flags[i].mode) && !(mode->mode & chmode_flags[i].mode))
212380e3 627 {
628 if(dir != MODE_DEL)
629 {
630 *mbuf++ = '-';
631 dir = MODE_DEL;
632 }
2a719c44 633 *mbuf++ = chmode_flags[i].letter;
212380e3 634 }
635 }
636
637 if(oldmode->limit && !mode->limit)
638 {
639 if(dir != MODE_DEL)
640 {
641 *mbuf++ = '-';
642 dir = MODE_DEL;
643 }
644 *mbuf++ = 'l';
645 }
646 if(oldmode->key[0] && !mode->key[0])
647 {
648 if(dir != MODE_DEL)
649 {
650 *mbuf++ = '-';
651 dir = MODE_DEL;
652 }
653 *mbuf++ = 'k';
654 len = ircsprintf(pbuf, "%s ", oldmode->key);
655 pbuf += len;
656 pargs++;
657 }
658 if(oldmode->join_num && !mode->join_num)
659 {
660 if(dir != MODE_DEL)
661 {
662 *mbuf++ = '-';
663 dir = MODE_DEL;
664 }
665 *mbuf++ = 'j';
666 }
667 if(oldmode->forward[0] && !mode->forward[0])
668 {
669 if(dir != MODE_DEL)
670 {
671 *mbuf++ = '-';
672 dir = MODE_DEL;
673 }
674 *mbuf++ = 'f';
675 }
676 if(mode->limit && oldmode->limit != mode->limit)
677 {
678 if(dir != MODE_ADD)
679 {
680 *mbuf++ = '+';
681 dir = MODE_ADD;
682 }
683 *mbuf++ = 'l';
684 len = ircsprintf(pbuf, "%d ", mode->limit);
685 pbuf += len;
686 pargs++;
687 }
688 if(mode->key[0] && strcmp(oldmode->key, mode->key))
689 {
690 if(dir != MODE_ADD)
691 {
692 *mbuf++ = '+';
693 dir = MODE_ADD;
694 }
695 *mbuf++ = 'k';
696 len = ircsprintf(pbuf, "%s ", mode->key);
697 pbuf += len;
698 pargs++;
699 }
700 if(mode->join_num && (oldmode->join_num != mode->join_num || oldmode->join_time != mode->join_time))
701 {
702 if(dir != MODE_ADD)
703 {
704 *mbuf++ = '+';
705 dir = MODE_ADD;
706 }
707 *mbuf++ = 'j';
708 len = ircsprintf(pbuf, "%d:%d ", mode->join_num, mode->join_time);
709 pbuf += len;
710 pargs++;
711 }
712 if(mode->forward[0] && strcmp(oldmode->forward, mode->forward) && ConfigChannel.use_forward)
713 {
714 if(dir != MODE_ADD)
715 {
716 *mbuf++ = '+';
717 dir = MODE_ADD;
718 }
719 *mbuf++ = 'f';
720 len = ircsprintf(pbuf, "%s ", mode->forward);
721 pbuf += len;
722 pargs++;
723 }
724 *mbuf = '\0';
725}
726
727/*
728 * remove_our_modes
729 *
730 * inputs -
731 * output -
732 * side effects -
733 */
734static void
735remove_our_modes(struct Channel *chptr, struct Client *source_p)
736{
737 struct membership *msptr;
08d11e34 738 rb_dlink_node *ptr;
212380e3 739 char lmodebuf[MODEBUFLEN];
740 char *lpara[MAXMODEPARAMS];
741 int count = 0;
742 int i;
743
744 mbuf = lmodebuf;
745 *mbuf++ = '-';
746
747 for (i = 0; i < MAXMODEPARAMS; i++)
748 lpara[i] = NULL;
749
08d11e34 750 RB_DLINK_FOREACH(ptr, chptr->members.head)
212380e3 751 {
752 msptr = ptr->data;
753
754 if(is_chanop(msptr))
755 {
756 msptr->flags &= ~CHFL_CHANOP;
757 lpara[count++] = msptr->client_p->name;
758 *mbuf++ = 'o';
759
760 /* +ov, might not fit so check. */
761 if(is_voiced(msptr))
762 {
763 if(count >= MAXMODEPARAMS)
764 {
765 *mbuf = '\0';
766 sendto_channel_local(ALL_MEMBERS, chptr,
767 ":%s MODE %s %s %s %s %s %s",
768 me.name, chptr->chname,
769 lmodebuf, lpara[0], lpara[1],
770 lpara[2], lpara[3]);
771
772 /* preserve the initial '-' */
773 mbuf = lmodebuf;
774 *mbuf++ = '-';
775 count = 0;
776
777 for (i = 0; i < MAXMODEPARAMS; i++)
778 lpara[i] = NULL;
779 }
780
781 msptr->flags &= ~CHFL_VOICE;
782 lpara[count++] = msptr->client_p->name;
783 *mbuf++ = 'v';
784 }
785 }
786 else if(is_voiced(msptr))
787 {
788 msptr->flags &= ~CHFL_VOICE;
789 lpara[count++] = msptr->client_p->name;
790 *mbuf++ = 'v';
791 }
792 else
793 continue;
794
795 if(count >= MAXMODEPARAMS)
796 {
797 *mbuf = '\0';
798 sendto_channel_local(ALL_MEMBERS, chptr,
799 ":%s MODE %s %s %s %s %s %s",
800 me.name, chptr->chname, lmodebuf,
801 lpara[0], lpara[1], lpara[2], lpara[3]);
802 mbuf = lmodebuf;
803 *mbuf++ = '-';
804 count = 0;
805
806 for (i = 0; i < MAXMODEPARAMS; i++)
807 lpara[i] = NULL;
808 }
809 }
810
811 if(count != 0)
812 {
813 *mbuf = '\0';
814 sendto_channel_local(ALL_MEMBERS, chptr,
815 ":%s MODE %s %s %s %s %s %s",
816 me.name, chptr->chname, lmodebuf,
817 EmptyString(lpara[0]) ? "" : lpara[0],
818 EmptyString(lpara[1]) ? "" : lpara[1],
819 EmptyString(lpara[2]) ? "" : lpara[2],
820 EmptyString(lpara[3]) ? "" : lpara[3]);
821
822 }
823}
824
825/* remove_ban_list()
826 *
827 * inputs - channel, source, list to remove, char of mode, caps needed
828 * outputs -
829 * side effects - given list is removed, with modes issued to local clients
830 * and non-TS6 servers.
831 */
832static void
833remove_ban_list(struct Channel *chptr, struct Client *source_p,
08d11e34 834 rb_dlink_list * list, char c, int cap, int mems)
212380e3 835{
836 static char lmodebuf[BUFSIZE];
837 static char lparabuf[BUFSIZE];
838 struct Ban *banptr;
08d11e34
WP
839 rb_dlink_node *ptr;
840 rb_dlink_node *next_ptr;
212380e3 841 char *pbuf;
842 int count = 0;
843 int cur_len, mlen, plen;
844
845 pbuf = lparabuf;
846
847 cur_len = mlen = ircsprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
848 mbuf = lmodebuf + mlen;
849
08d11e34 850 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
212380e3 851 {
852 banptr = ptr->data;
853
854 /* trailing space, and the mode letter itself */
855 plen = strlen(banptr->banstr) + 2;
856
857 if(count >= MAXMODEPARAMS || (cur_len + plen) > BUFSIZE - 4)
858 {
859 /* remove trailing space */
860 *mbuf = '\0';
861 *(pbuf - 1) = '\0';
862
863 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
864 /* Tricky tricky. If we changed source_p to &me
865 * in ms_sjoin(), this still won't send stuff
866 * where it should not be sent, because the
867 * real source_p does TS6 -- jilles */
868 sendto_server(source_p, chptr, cap, CAP_TS6, "%s %s", lmodebuf, lparabuf);
869
870 cur_len = mlen;
871 mbuf = lmodebuf + mlen;
872 pbuf = lparabuf;
873 count = 0;
874 }
875
876 *mbuf++ = c;
877 cur_len += plen;
878 pbuf += ircsprintf(pbuf, "%s ", banptr->banstr);
879 count++;
880
881 free_ban(banptr);
882 }
883
884 *mbuf = '\0';
885 *(pbuf - 1) = '\0';
886 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
887 sendto_server(source_p, chptr, cap, CAP_TS6, "%s %s", lmodebuf, lparabuf);
888
889 list->head = list->tail = NULL;
890 list->length = 0;
891}