/[svn]/ircd-hybrid-8/modules/core/m_sjoin.c
ViewVC logotype

Contents of /ircd-hybrid-8/modules/core/m_sjoin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1175 - (show annotations)
Sun Aug 14 10:47:48 2011 UTC (8 years, 10 months ago) by michael
File MIME type: text/x-chdr
File size: 21054 byte(s)
- several fixes to services compatibility mode

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

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28