ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_sjoin.c
Revision: 491
Committed: Wed Mar 1 14:51:05 2006 UTC (18 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 20677 byte(s)
Log Message:
- Got rid of extra strlenS and redundant hash_find_channel() calls
- Cleaned up channel name validation routines
- mo_force: don't allow servers to be added to a channel


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

Properties

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