ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_sjoin.c
Revision: 741
Committed: Sun Jul 23 13:49:20 2006 UTC (19 years, 1 month ago) by adx
Content type: text/x-csrc
File size: 20648 byte(s)
Log Message:
+ removed s_conf.h and superseded parts of s_conf.c

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * m_sjoin.c: Joins a user to a channel.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "handlers.h"
27 #include "channel.h"
28 #include "channel_mode.h"
29 #include "client.h"
30 #include "hash.h"
31 #include "ircd.h"
32 #include "numeric.h"
33 #include "send.h"
34 #include "common.h"
35 #include "msg.h"
36 #include "parse.h"
37 #include "conf/modules.h"
38 #include "s_serv.h"
39
40 static void ms_sjoin(struct Client *, struct Client *, int, char *[]);
41
42 struct Message sjoin_msgtab = {
43 "SJOIN", 0, 0, 0, 0, MFLG_SLOW, 0,
44 { m_unregistered, m_ignore, ms_sjoin, m_ignore, m_ignore, m_ignore }
45 };
46
47 INIT_MODULE(m_sjoin, "$Revision$")
48 {
49 mod_add_cmd(&sjoin_msgtab);
50 }
51
52 CLEANUP_MODULE
53 {
54 mod_del_cmd(&sjoin_msgtab);
55 }
56
57 static char modebuf[MODEBUFLEN];
58 static char parabuf[MODEBUFLEN];
59 static char sendbuf[MODEBUFLEN];
60 static const char *para[MAXMODEPARAMS];
61 static char *mbuf;
62 static int pargs;
63
64 static void set_final_mode(struct Mode *, struct Mode *);
65 static void remove_our_modes(struct Channel *, struct Client *);
66 static void remove_a_mode(struct Channel *, struct Client *, int, char);
67 static void remove_ban_list(struct Channel *, struct Client *, dlink_list *, char, int);
68
69 /* ms_sjoin()
70 *
71 * parv[0] - sender
72 * parv[1] - TS
73 * parv[2] - channel
74 * parv[3] - modes + n arguments (key and/or limit)
75 * parv[4+n] - flags+nick list (all in one parameter)
76 *
77 * process a SJOIN, taking the TS's into account to either ignore the
78 * incoming modes or undo the existing ones or merge them, and JOIN
79 * all the specified users while sending JOIN/MODEs to local clients
80 */
81 static void
82 ms_sjoin(struct Client *client_p, struct Client *source_p,
83 int parc, char *parv[])
84 {
85 struct Channel *chptr;
86 struct Client *target_p;
87 time_t newts;
88 time_t oldts;
89 time_t tstosend;
90 struct Mode mode, *oldmode;
91 int args = 0;
92 char keep_our_modes = YES;
93 char keep_new_modes = YES;
94 char have_many_nicks = NO;
95 int lcount;
96 char nick_prefix[4];
97 char uid_prefix[4];
98 char *np, *up;
99 int len_nick = 0;
100 int len_uid = 0;
101 int isnew = 0;
102 int buflen = 0;
103 int slen;
104 unsigned int fl;
105 char *s;
106 char *sptr;
107 char nick_buf[IRCD_BUFSIZE]; /* buffer for modes and prefix */
108 char uid_buf[IRCD_BUFSIZE]; /* buffer for modes/prefixes for CAP_TS6 servers */
109 char *nick_ptr, *uid_ptr; /* pointers used for making the two mode/prefix buffers */
110 char *p; /* pointer used making sjbuf */
111 dlink_node *m;
112 const char *servername = (ConfigServerHide.hide_servers || IsHidden(source_p)) ?
113 me.name : source_p->name;
114
115 if (IsClient(source_p) || parc < 5)
116 return;
117
118 /* SJOIN's for local channels can't happen. */
119 if (*parv[2] != '#')
120 return;
121
122 if (!check_channel_name(parv[2], 0))
123 {
124 sendto_realops_flags(UMODE_DEBUG, L_ALL,
125 "*** Too long or invalid channel name from %s: %s",
126 client_p->name, parv[2]);
127 return;
128 }
129
130 modebuf[0] = '\0';
131 mbuf = modebuf;
132 pargs = 0;
133 newts = atol(parv[1]);
134
135 mode.mode = 0;
136 mode.limit = 0;
137 mode.key[0] = '\0';
138 s = parv[3];
139
140 while (*s)
141 {
142 switch (*(s++))
143 {
144 case 't':
145 mode.mode |= MODE_TOPICLIMIT;
146 break;
147 case 'n':
148 mode.mode |= MODE_NOPRIVMSGS;
149 break;
150 case 's':
151 mode.mode |= MODE_SECRET;
152 break;
153 case 'm':
154 mode.mode |= MODE_MODERATED;
155 break;
156 case 'i':
157 mode.mode |= MODE_INVITEONLY;
158 break;
159 case 'p':
160 mode.mode |= MODE_PARANOID;
161 break;
162 case 'k':
163 strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
164 args++;
165 if (parc < 5+args)
166 return;
167 break;
168 case 'l':
169 mode.limit = atoi(parv[4 + args]);
170 args++;
171 if (parc < 5+args)
172 return;
173 break;
174 }
175 }
176
177 parabuf[0] = '\0';
178
179 if ((chptr = hash_find_channel(parv[2])) == NULL)
180 {
181 isnew = 1;
182 chptr = make_channel(parv[2]);
183 }
184
185 oldts = chptr->channelts;
186 oldmode = &chptr->mode;
187
188 if (ConfigFileEntry.ignore_bogus_ts)
189 {
190 if (newts < 800000000)
191 {
192 sendto_realops_flags(UMODE_DEBUG, L_ALL,
193 "*** Bogus TS %lu on %s ignored from %s",
194 (unsigned long)newts, chptr->chname,
195 client_p->name);
196
197 newts = (oldts == 0) ? 0 : 800000000;
198 }
199 }
200 else
201 {
202 if (!newts && !isnew && oldts)
203 {
204 sendto_channel_local(ALL_MEMBERS, NO, chptr,
205 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to 0",
206 me.name, chptr->chname, chptr->chname, (unsigned long)oldts);
207 sendto_realops_flags(UMODE_ALL, L_ALL,
208 "Server %s changing TS on %s from %lu to 0",
209 source_p->name, chptr->chname, (unsigned long)oldts);
210 }
211 }
212
213 if (isnew)
214 chptr->channelts = tstosend = newts;
215 else if (newts == 0 || oldts == 0)
216 chptr->channelts = tstosend = 0;
217 else if (newts == oldts)
218 tstosend = oldts;
219 else if (newts < oldts)
220 {
221 keep_our_modes = NO;
222 chptr->channelts = tstosend = newts;
223 }
224 else
225 {
226 keep_new_modes = NO;
227 tstosend = oldts;
228 }
229
230 if (!keep_new_modes)
231 mode = *oldmode;
232 else if (keep_our_modes)
233 {
234 mode.mode |= oldmode->mode;
235 if (oldmode->limit > mode.limit)
236 mode.limit = oldmode->limit;
237 if (strcmp(mode.key, oldmode->key) < 0)
238 strcpy(mode.key, oldmode->key);
239 }
240
241 set_final_mode(&mode, oldmode);
242 chptr->mode = mode;
243
244 /* Lost the TS, other side wins, so remove modes on this side */
245 if (!keep_our_modes)
246 {
247 remove_our_modes(chptr, source_p);
248 sendto_channel_local(ALL_MEMBERS, NO, chptr,
249 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to %lu",
250 me.name, chptr->chname, chptr->chname,
251 (unsigned long)oldts, (unsigned long)newts);
252 }
253
254 if (*modebuf != '\0')
255 {
256 /* This _SHOULD_ be to ALL_MEMBERS
257 * It contains only +imnpstlk, etc */
258 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s %s %s",
259 servername, chptr->chname, modebuf, parabuf);
260 }
261
262 if (parv[3][0] != '0' && keep_new_modes)
263 {
264 channel_modes(chptr, source_p, modebuf, parabuf);
265 }
266 else
267 {
268 modebuf[0] = '0';
269 modebuf[1] = '\0';
270 }
271
272 buflen = ircsprintf(nick_buf, ":%s SJOIN %lu %s %s %s:",
273 source_p->name, (unsigned long)tstosend,
274 chptr->chname, modebuf, parabuf);
275 nick_ptr = nick_buf + buflen;
276
277 buflen = ircsprintf(uid_buf, ":%s SJOIN %lu %s %s %s:",
278 ID(source_p), (unsigned long)tstosend,
279 chptr->chname, modebuf, parabuf);
280 uid_ptr = uid_buf + buflen;
281
282 /* check we can fit a nick on the end, as well as \r\n and a prefix "
283 * @%+", and a space.
284 */
285 if (buflen >= (IRCD_BUFSIZE - LIBIO_MAX(NICKLEN, IDLEN) - 2 - 3 - 1))
286 {
287 sendto_realops_flags(UMODE_ALL, L_ALL,
288 "Long SJOIN from server: %s(via %s) (ignored)",
289 source_p->name, client_p->name);
290 return;
291 }
292
293 mbuf = modebuf;
294 sendbuf[0] = '\0';
295 pargs = 0;
296
297 *mbuf++ = '+';
298
299 s = parv[args + 4];
300 while (*s == ' ')
301 s++;
302 if ((p = strchr(s, ' ')) != NULL)
303 {
304 *p++ = '\0';
305 while (*p == ' ')
306 p++;
307 have_many_nicks = *p;
308 }
309
310 while (*s)
311 {
312 int valid_mode = YES;
313 fl = 0;
314
315 do
316 {
317 switch (*s)
318 {
319 case '@':
320 fl |= CHFL_CHANOP;
321 s++;
322 break;
323 #ifdef HALFOPS
324 case '%':
325 fl |= CHFL_HALFOP;
326 s++;
327 break;
328 #endif
329 case '+':
330 fl |= CHFL_VOICE;
331 s++;
332 break;
333 default:
334 valid_mode = NO;
335 break;
336 }
337 } while (valid_mode);
338
339 target_p = find_chasing(source_p, s, NULL);
340
341 /*
342 * if the client doesnt exist, or if its fake direction/server, skip.
343 * we cannot send ERR_NOSUCHNICK here because if its a UID, we cannot
344 * lookup the nick, and its better to never send the numeric than only
345 * sometimes.
346 */
347 if (target_p == NULL ||
348 target_p->from != client_p ||
349 !IsClient(target_p))
350 {
351 goto nextnick;
352 }
353
354 len_nick = strlen(target_p->name);
355 len_uid = strlen(ID(target_p));
356
357 np = nick_prefix;
358 up = uid_prefix;
359
360 if (keep_new_modes)
361 {
362 if (fl & CHFL_CHANOP)
363 {
364 *np++ = '@';
365 *up++ = '@';
366 len_nick++;
367 len_uid++;
368 }
369 #ifdef HALFOPS
370 if (fl & CHFL_HALFOP)
371 {
372 *np++ = '%';
373 *up++ = '%';
374 len_nick++;
375 len_uid++;
376 }
377 #endif
378 if (fl & CHFL_VOICE)
379 {
380 *np++ = '+';
381 *up++ = '+';
382 len_nick++;
383 len_uid++;
384 }
385 }
386 else
387 {
388 if (fl & (CHFL_CHANOP|CHFL_HALFOP))
389 fl = CHFL_DEOPPED;
390 else
391 fl = 0;
392 }
393
394 *np = *up = '\0';
395
396 if ((nick_ptr - nick_buf + len_nick) > (IRCD_BUFSIZE - 2))
397 {
398 sendto_server(client_p, NULL, chptr, 0, CAP_TS6, "%s", nick_buf);
399
400 buflen = ircsprintf(nick_buf, ":%s SJOIN %lu %s %s %s:",
401 source_p->name, (unsigned long)tstosend,
402 chptr->chname, modebuf, parabuf);
403 nick_ptr = nick_buf + buflen;
404 }
405
406 nick_ptr += ircsprintf(nick_ptr, "%s%s ", nick_prefix, target_p->name);
407
408 if ((uid_ptr - uid_buf + len_uid) > (IRCD_BUFSIZE - 2))
409 {
410 sendto_server(client_p, NULL, chptr, CAP_TS6, 0, "%s", uid_buf);
411
412 buflen = ircsprintf(uid_buf, ":%s SJOIN %lu %s %s %s:",
413 ID(source_p), (unsigned long)tstosend,
414 chptr->chname, modebuf, parabuf);
415 uid_ptr = uid_buf + buflen;
416 }
417
418 uid_ptr += ircsprintf(uid_ptr, "%s%s ", uid_prefix, ID(target_p));
419
420 if (!IsMember(target_p, chptr))
421 {
422 add_user_to_channel(chptr, target_p, fl, !have_many_nicks);
423 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s JOIN :%s",
424 target_p->name, target_p->username,
425 target_p->host, chptr->chname);
426 }
427
428 if (fl & CHFL_CHANOP)
429 {
430 *mbuf++ = 'o';
431 para[pargs++] = target_p->name;
432
433 if (pargs >= MAXMODEPARAMS)
434 {
435 /*
436 * Ok, the code is now going to "walk" through
437 * sendbuf, filling in para strings. So, I will use sptr
438 * to point into the sendbuf.
439 * Notice, that ircsprintf() returns the number of chars
440 * successfully inserted into string.
441 * - Dianora
442 */
443
444 sptr = sendbuf;
445 *mbuf = '\0';
446 for(lcount = 0; lcount < MAXMODEPARAMS; lcount++)
447 {
448 slen = ircsprintf(sptr, " %s", para[lcount]); /* see? */
449 sptr += slen; /* ready for next */
450 }
451 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s %s%s",
452 servername, chptr->chname, modebuf, sendbuf);
453 mbuf = modebuf;
454 *mbuf++ = '+';
455
456 sendbuf[0] = '\0';
457 pargs = 0;
458 }
459 }
460 #ifdef HALFOPS
461 if (fl & CHFL_HALFOP)
462 {
463 *mbuf++ = 'h';
464 para[pargs++] = target_p->name;
465
466 if (pargs >= MAXMODEPARAMS)
467 {
468 sptr = sendbuf;
469 *mbuf = '\0';
470 for(lcount = 0; lcount < MAXMODEPARAMS; lcount++)
471 {
472 slen = ircsprintf(sptr, " %s", para[lcount]);
473 sptr += slen;
474 }
475 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s %s%s",
476 servername, chptr->chname, modebuf, sendbuf);
477
478 mbuf = modebuf;
479 *mbuf++ = '+';
480
481 sendbuf[0] = '\0';
482 pargs = 0;
483 }
484 }
485 #endif
486 if (fl & CHFL_VOICE)
487 {
488 *mbuf++ = 'v';
489 para[pargs++] = target_p->name;
490
491 if (pargs >= MAXMODEPARAMS)
492 {
493 sptr = sendbuf;
494 *mbuf = '\0';
495 for (lcount = 0; lcount < MAXMODEPARAMS; lcount++)
496 {
497 slen = ircsprintf(sptr, " %s", para[lcount]);
498 sptr += slen;
499 }
500 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s %s%s",
501 servername, chptr->chname, modebuf, sendbuf);
502
503 mbuf = modebuf;
504 *mbuf++ = '+';
505
506 sendbuf[0] = '\0';
507 pargs = 0;
508 }
509 }
510
511 nextnick:
512 if ((s = p) == NULL)
513 break;
514 while (*s == ' ')
515 s++;
516 if ((p = strchr(s, ' ')) != NULL)
517 {
518 *p++ = 0;
519 while (*p == ' ')
520 p++;
521 }
522 }
523
524 *mbuf = '\0';
525 *(nick_ptr - 1) = '\0';
526 *(uid_ptr - 1) = '\0';
527
528 /*
529 * checking for lcount < MAXMODEPARAMS at this time is wrong
530 * since the code has already verified above that pargs < MAXMODEPARAMS
531 * checking for para[lcount] != '\0' is also wrong, since
532 * there is no place where para[lcount] is set!
533 * - Dianora
534 */
535
536 if (pargs != 0)
537 {
538 sptr = sendbuf;
539
540 for (lcount = 0; lcount < pargs; lcount++)
541 {
542 slen = ircsprintf(sptr, " %s", para[lcount]);
543 sptr += slen;
544 }
545
546 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s %s%s",
547 servername, chptr->chname, modebuf, sendbuf);
548 }
549
550 /* If this happens, its the result of a malformed SJOIN
551 * a remnant from the old persistent channel code. *sigh*
552 * Or it could be the result of a client just leaving
553 * and leaving us with a channel formed just as the client parts.
554 * - Dianora
555 */
556
557 if ((dlink_list_length(&chptr->members) == 0) && isnew)
558 {
559 destroy_channel(chptr);
560 return;
561 }
562
563 if (parv[4 + args][0] == '\0')
564 return;
565
566 /* relay the SJOIN to other servers */
567 DLINK_FOREACH(m, serv_list.head)
568 {
569 target_p = m->data;
570
571 if (target_p == client_p)
572 continue;
573
574 if (IsCapable(target_p, CAP_TS6))
575 sendto_one(target_p, "%s", uid_buf);
576 else
577 sendto_one(target_p, "%s", nick_buf);
578 }
579
580 if (HasID(source_p) && !keep_our_modes)
581 {
582 if (dlink_list_length(&chptr->banlist) > 0)
583 remove_ban_list(chptr, client_p, &chptr->banlist,
584 'b', NOCAPS);
585
586 if (dlink_list_length(&chptr->exceptlist) > 0)
587 remove_ban_list(chptr, client_p, &chptr->exceptlist,
588 'e', CAP_EX);
589
590 if (dlink_list_length(&chptr->invexlist) > 0)
591 remove_ban_list(chptr, client_p, &chptr->invexlist,
592 'I', CAP_IE);
593 clear_ban_cache(chptr);
594 }
595 }
596
597 /* set_final_mode
598 *
599 * inputs - channel mode
600 * - old channel mode
601 * output - NONE
602 * side effects - walk through all the channel modes turning off modes
603 * that were on in oldmode but aren't on in mode.
604 * Then walk through turning on modes that are on in mode
605 * but were not set in oldmode.
606 */
607
608 static const struct mode_letter
609 {
610 unsigned int mode;
611 unsigned char letter;
612 } flags[] = {
613 { MODE_NOPRIVMSGS, 'n' },
614 { MODE_TOPICLIMIT, 't' },
615 { MODE_SECRET, 's' },
616 { MODE_MODERATED, 'm' },
617 { MODE_INVITEONLY, 'i' },
618 { MODE_PARANOID, 'p' },
619 { 0, '\0' }
620 };
621
622 static void
623 set_final_mode(struct Mode *mode, struct Mode *oldmode)
624 {
625 char *pbuf = parabuf;
626 int len;
627 int i;
628
629 *mbuf++ = '-';
630
631 for (i = 0; flags[i].letter; i++)
632 {
633 if ((flags[i].mode & oldmode->mode) &&
634 !(flags[i].mode & mode->mode))
635 *mbuf++ = flags[i].letter;
636 }
637
638 if (oldmode->limit != 0 && mode->limit == 0)
639 *mbuf++ = 'l';
640
641 if (oldmode->key[0] && !mode->key[0])
642 {
643 *mbuf++ = 'k';
644 len = ircsprintf(pbuf, "%s ", oldmode->key);
645 pbuf += len;
646 pargs++;
647 }
648
649 if (*(mbuf-1) == '-')
650 *(mbuf-1) = '+';
651 else
652 *mbuf++ = '+';
653
654 for (i = 0; flags[i].letter; i++)
655 {
656 if ((flags[i].mode & mode->mode) &&
657 !(flags[i].mode & oldmode->mode))
658 *mbuf++ = flags[i].letter;
659 }
660
661 if (mode->limit != 0 && oldmode->limit != mode->limit)
662 {
663 *mbuf++ = 'l';
664 len = ircsprintf(pbuf, "%d ", mode->limit);
665 pbuf += len;
666 pargs++;
667 }
668
669 if (mode->key[0] && strcmp(oldmode->key, mode->key))
670 {
671 *mbuf++ = 'k';
672 len = ircsprintf(pbuf, "%s ", mode->key);
673 pbuf += len;
674 pargs++;
675 }
676 if (*(mbuf-1) == '+')
677 *(mbuf-1) = '\0';
678 else
679 *mbuf = '\0';
680 }
681
682 /* remove_our_modes()
683 *
684 * inputs - pointer to channel to remove modes from
685 * - client pointer
686 * output - NONE
687 * side effects - Go through the local members, remove all their
688 * chanop modes etc., this side lost the TS.
689 */
690 static void
691 remove_our_modes(struct Channel *chptr, struct Client *source_p)
692 {
693 remove_a_mode(chptr, source_p, CHFL_CHANOP, 'o');
694 #ifdef HALFOPS
695 remove_a_mode(chptr, source_p, CHFL_HALFOP, 'h');
696 #endif
697 remove_a_mode(chptr, source_p, CHFL_VOICE, 'v');
698 }
699
700 /* remove_a_mode()
701 *
702 * inputs - pointer to channel
703 * - server or client removing the mode
704 * - mask o/h/v mask to be removed
705 * - flag o/h/v to be removed
706 * output - NONE
707 * side effects - remove ONE mode from all members of a channel
708 */
709 static void
710 remove_a_mode(struct Channel *chptr, struct Client *source_p,
711 int mask, char flag)
712 {
713 dlink_node *ptr;
714 struct Membership *ms;
715 char lmodebuf[MODEBUFLEN];
716 char *sp=sendbuf;
717 const char *lpara[MAXMODEPARAMS];
718 int count = 0;
719 int i;
720 int l;
721
722 mbuf = lmodebuf;
723 *mbuf++ = '-';
724 *sp = '\0';
725
726 DLINK_FOREACH(ptr, chptr->members.head)
727 {
728 ms = ptr->data;
729
730 if ((ms->flags & mask) == 0)
731 continue;
732
733 ms->flags &= ~mask;
734
735 lpara[count++] = ms->client_p->name;
736
737 *mbuf++ = flag;
738
739 if (count >= MAXMODEPARAMS)
740 {
741 for(i = 0; i < MAXMODEPARAMS; i++)
742 {
743 l = ircsprintf(sp, " %s", lpara[i]);
744 sp += l;
745 }
746
747 *mbuf = '\0';
748 sendto_channel_local(ALL_MEMBERS, NO, chptr,
749 ":%s MODE %s %s%s",
750 (IsHidden(source_p) ||
751 ConfigServerHide.hide_servers) ?
752 me.name : source_p->name,
753 chptr->chname, lmodebuf, sendbuf);
754 mbuf = lmodebuf;
755 *mbuf++ = '-';
756 count = 0;
757 sp = sendbuf;
758 *sp = '\0';
759 }
760 }
761
762 if (count != 0)
763 {
764 *mbuf = '\0';
765 for(i = 0; i < count; i++)
766 {
767 l = ircsprintf(sp, " %s", lpara[i]);
768 sp += l;
769 }
770 sendto_channel_local(ALL_MEMBERS, NO, chptr,
771 ":%s MODE %s %s%s",
772 (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
773 me.name : source_p->name,
774 chptr->chname, lmodebuf, sendbuf);
775 }
776 }
777
778 /* remove_ban_list()
779 *
780 * inputs - channel, source, list to remove, char of mode, caps required
781 * outputs - none
782 * side effects - given ban list is removed, modes are sent to local clients and
783 * non-ts6 servers linked through another uplink other than source_p
784 */
785 static void
786 remove_ban_list(struct Channel *chptr, struct Client *source_p,
787 dlink_list *list, char c, int cap)
788 {
789 char lmodebuf[MODEBUFLEN];
790 char lparabuf[IRCD_BUFSIZE];
791 struct Ban *banptr = NULL;
792 dlink_node *ptr = NULL;
793 dlink_node *next_ptr = NULL;
794 char *pbuf = NULL;
795 int count = 0;
796 int cur_len, mlen, plen;
797
798 pbuf = lparabuf;
799
800 cur_len = mlen = ircsprintf(lmodebuf, ":%s MODE %s -",
801 source_p->name, chptr->chname);
802 mbuf = lmodebuf + mlen;
803
804 DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
805 {
806 banptr = ptr->data;
807
808 plen = banptr->len + 4; /* another +b and "!@ " */
809 if (count >= MAXMODEPARAMS ||
810 (cur_len + 1 /* space between */ + (plen - 1)) > IRCD_BUFSIZE - 2)
811 {
812 /* NUL-terminate and remove trailing space */
813 *mbuf = *(pbuf - 1) = '\0';
814 sendto_channel_local(ALL_MEMBERS, NO, chptr, "%s %s",
815 lmodebuf, lparabuf);
816 sendto_server(source_p, NULL, chptr, cap, CAP_TS6,
817 "%s %s", lmodebuf, lparabuf);
818
819 cur_len = mlen;
820 mbuf = lmodebuf + mlen;
821 pbuf = lparabuf;
822 count = 0;
823 }
824
825 *mbuf++ = c;
826 cur_len += plen;
827 pbuf += ircsprintf(pbuf, "%s!%s@%s ", banptr->name, banptr->username,
828 banptr->host);
829 ++count;
830
831 remove_ban(banptr, list);
832 }
833
834 *mbuf = *(pbuf - 1) = '\0';
835 sendto_channel_local(ALL_MEMBERS, NO, chptr, "%s %s", lmodebuf, lparabuf);
836 sendto_server(source_p, NULL, chptr, cap, CAP_TS6,
837 "%s %s", lmodebuf, lparabuf);
838 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision