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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 632 - (show annotations)
Thu Jun 1 10:53:00 2006 UTC (13 years, 4 months ago) by michael
File MIME type: text/x-chdr
File size: 22222 byte(s)
- Added channel::disable_fake_channels which disallows creation of channels
  that have ascii 2, 3, 31 and 160 in their names.
- Minor improvements and cleanups to channel name validation routines
  backported from 7.3

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

Properties

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

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