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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations)
Sun Oct 2 20:41:23 2005 UTC (15 years, 9 months ago) by knight
File MIME type: text/x-chdr
File size: 22040 byte(s)
- svn:keywords

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

Properties

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

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