ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/core/m_sjoin.c
Revision: 885
Committed: Wed Oct 31 18:09:24 2007 UTC (16 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_sjoin.c
File size: 21163 byte(s)
Log Message:
- Removed LazyLinks in 7.2 to stop people from asking why we keep
  broken code for half a decade. LL will be implemented in a smarter
  fashion in due time

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

Properties

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