ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_sjoin.c
Revision: 1937
Committed: Sat May 4 20:54:13 2013 UTC (12 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 21424 byte(s)
Log Message:
-  Implemented channel mode +c. Known from other ircds, this mode basically
   prevents users from sending messages including control codes to a channel
   that has this mode set

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

Properties

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