ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/branches/newio/modules/core/m_sjoin.c
Revision: 2417
Committed: Sun Jul 21 18:11:50 2013 UTC (10 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 21496 byte(s)
Log Message:
- Change command message handlers to int type

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

Properties

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