/[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 1028 - (show annotations)
Sun Nov 8 13:03:38 2009 UTC (11 years, 5 months ago) by michael
File MIME type: text/x-chdr
File size: 21144 byte(s)
- move ircd-hybrid-7.2 to trunk

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

Properties

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

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