ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/branches/newio/modules/core/m_sjoin.c
Revision: 2477
Committed: Wed Oct 23 13:53:47 2013 UTC (12 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 21410 byte(s)
Log Message:
- find_person(): fixed naming convention
- find_chasing(): reduced required arguments

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

Properties

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