ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_sjoin.c
Revision: 1618
Committed: Tue Oct 30 21:04:38 2012 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/modules/core/m_sjoin.c
File size: 21038 byte(s)
Log Message:
- Made m_globops() and ms_globops() use sendto_realops_flags()
- Added message-type parameter to sendto_realops_flags() which can be one of
  SEND_NOTICE, SEND_GLOBAL, SEND_LOCOPS
- Forward-port -r1617

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 "sprintf_irc.h"
33 #include "ircd.h"
34 #include "numeric.h"
35 #include "send.h"
36 #include "parse.h"
37 #include "modules.h"
38 #include "s_serv.h"
39 #include "conf.h"
40 #include "s_misc.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 void
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;
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;
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 't':
127 mode.mode |= MODE_TOPICLIMIT;
128 break;
129 case 'n':
130 mode.mode |= MODE_NOPRIVMSGS;
131 break;
132 case 's':
133 mode.mode |= MODE_SECRET;
134 break;
135 case 'm':
136 mode.mode |= MODE_MODERATED;
137 break;
138 case 'i':
139 mode.mode |= MODE_INVITEONLY;
140 break;
141 case 'p':
142 mode.mode |= MODE_PRIVATE;
143 break;
144 case 'r':
145 mode.mode |= MODE_REGISTERED;
146 break;
147 case 'O':
148 mode.mode |= MODE_OPERONLY;
149 break;
150 case 'S':
151 mode.mode |= MODE_SSLONLY;
152 break;
153 case 'k':
154 strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
155 args++;
156
157 if (parc < 5 + args)
158 return;
159 break;
160 case 'l':
161 mode.limit = atoi(parv[4 + args]);
162 args++;
163
164 if (parc < 5 + args)
165 return;
166 break;
167 }
168 }
169
170 if ((chptr = hash_find_channel(parv[2])) == NULL)
171 {
172 isnew = 1;
173 chptr = make_channel(parv[2]);
174 }
175
176 parabuf[0] = '\0';
177 oldts = chptr->channelts;
178 oldmode = &chptr->mode;
179
180 if (ConfigFileEntry.ignore_bogus_ts)
181 {
182 if (newts < 800000000)
183 {
184 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
185 "*** Bogus TS %lu on %s ignored from %s",
186 (unsigned long)newts, chptr->chname,
187 client_p->name);
188
189 newts = (oldts == 0) ? 0 : 800000000;
190 }
191 }
192 else
193 {
194 if (!newts && !isnew && oldts)
195 {
196 sendto_channel_local(ALL_MEMBERS, 0, chptr,
197 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to 0",
198 me.name, chptr->chname, chptr->chname, (unsigned long)oldts);
199 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
200 "Server %s changing TS on %s from %lu to 0",
201 source_p->name, chptr->chname, (unsigned long)oldts);
202 }
203 }
204
205 if (isnew)
206 chptr->channelts = tstosend = newts;
207 else if (newts == 0 || oldts == 0)
208 chptr->channelts = tstosend = 0;
209 else if (newts == oldts)
210 tstosend = oldts;
211 else if (newts < oldts)
212 {
213 keep_our_modes = 0;
214 chptr->channelts = tstosend = newts;
215 }
216 else
217 {
218 keep_new_modes = 0;
219 tstosend = oldts;
220 }
221
222 if (!keep_new_modes)
223 mode = *oldmode;
224 else if (keep_our_modes)
225 {
226 mode.mode |= oldmode->mode;
227 if (oldmode->limit > mode.limit)
228 mode.limit = oldmode->limit;
229 if (strcmp(mode.key, oldmode->key) < 0)
230 strcpy(mode.key, oldmode->key);
231 }
232 set_final_mode(&mode, oldmode);
233 chptr->mode = mode;
234
235 /* Lost the TS, other side wins, so remove modes on this side */
236 if (!keep_our_modes)
237 {
238 remove_our_modes(chptr, source_p);
239
240 if (chptr->topic[0])
241 {
242 set_channel_topic(chptr, "", "", 0);
243 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s TOPIC %s :",
244 (IsHidden(source_p) ||
245 ConfigServerHide.hide_servers) ?
246 me.name : source_p->name, chptr->chname);
247 }
248
249 sendto_channel_local(ALL_MEMBERS, 0, 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, 0, 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, SEND_NOTICE,
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 = 1;
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 = 0;
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 *np = *up = '\0';
395
396 if ((nick_ptr - nick_buf + len_nick) > (IRCD_BUFSIZE - 2))
397 {
398 sendto_server(client_p, 0, CAP_TS6, "%s", nick_buf);
399
400 buflen = ircsprintf(nick_buf, ":%s SJOIN %lu %s %s %s:",
401 source_p->name, (unsigned long)tstosend,
402 chptr->chname, modebuf, parabuf);
403 nick_ptr = nick_buf + buflen;
404 }
405
406 nick_ptr += ircsprintf(nick_ptr, "%s%s ", nick_prefix, target_p->name);
407
408 if ((uid_ptr - uid_buf + len_uid) > (IRCD_BUFSIZE - 2))
409 {
410 sendto_server(client_p, CAP_TS6, 0, "%s", uid_buf);
411
412 buflen = ircsprintf(uid_buf, ":%s SJOIN %lu %s %s %s:",
413 ID(source_p), (unsigned long)tstosend,
414 chptr->chname, modebuf, parabuf);
415 uid_ptr = uid_buf + buflen;
416 }
417
418 uid_ptr += ircsprintf(uid_ptr, "%s%s ", uid_prefix, ID(target_p));
419
420 if (!IsMember(target_p, chptr))
421 {
422 add_user_to_channel(chptr, target_p, fl, !have_many_nicks);
423 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
424 target_p->name, target_p->username,
425 target_p->host, chptr->chname);
426 }
427
428 if (fl & CHFL_CHANOP)
429 {
430 *mbuf++ = 'o';
431 para[pargs++] = target_p->name;
432
433 if (pargs >= MAXMODEPARAMS)
434 {
435 /*
436 * Ok, the code is now going to "walk" through
437 * sendbuf, filling in para strings. So, I will use sptr
438 * to point into the sendbuf.
439 * Notice, that ircsprintf() returns the number of chars
440 * successfully inserted into string.
441 * - Dianora
442 */
443
444 sptr = sendbuf;
445 *mbuf = '\0';
446 for(lcount = 0; lcount < MAXMODEPARAMS; lcount++)
447 {
448 slen = ircsprintf(sptr, " %s", para[lcount]); /* see? */
449 sptr += slen; /* ready for next */
450 }
451 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
452 servername, chptr->chname, modebuf, sendbuf);
453 mbuf = modebuf;
454 *mbuf++ = '+';
455
456 sendbuf[0] = '\0';
457 pargs = 0;
458 }
459 }
460 #ifdef HALFOPS
461 if (fl & CHFL_HALFOP)
462 {
463 *mbuf++ = 'h';
464 para[pargs++] = target_p->name;
465
466 if (pargs >= MAXMODEPARAMS)
467 {
468 sptr = sendbuf;
469 *mbuf = '\0';
470 for(lcount = 0; lcount < MAXMODEPARAMS; lcount++)
471 {
472 slen = ircsprintf(sptr, " %s", para[lcount]);
473 sptr += slen;
474 }
475 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
476 servername, chptr->chname, modebuf, sendbuf);
477
478 mbuf = modebuf;
479 *mbuf++ = '+';
480
481 sendbuf[0] = '\0';
482 pargs = 0;
483 }
484 }
485 #endif
486 if (fl & CHFL_VOICE)
487 {
488 *mbuf++ = 'v';
489 para[pargs++] = target_p->name;
490
491 if (pargs >= MAXMODEPARAMS)
492 {
493 sptr = sendbuf;
494 *mbuf = '\0';
495 for (lcount = 0; lcount < MAXMODEPARAMS; lcount++)
496 {
497 slen = ircsprintf(sptr, " %s", para[lcount]);
498 sptr += slen;
499 }
500 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
501 servername, chptr->chname, modebuf, sendbuf);
502
503 mbuf = modebuf;
504 *mbuf++ = '+';
505
506 sendbuf[0] = '\0';
507 pargs = 0;
508 }
509 }
510
511 nextnick:
512 if ((s = p) == NULL)
513 break;
514 while (*s == ' ')
515 s++;
516 if ((p = strchr(s, ' ')) != NULL)
517 {
518 *p++ = 0;
519 while (*p == ' ')
520 p++;
521 }
522 }
523
524 *mbuf = '\0';
525 *(nick_ptr - 1) = '\0';
526 *(uid_ptr - 1) = '\0';
527
528 /*
529 * checking for lcount < MAXMODEPARAMS at this time is wrong
530 * since the code has already verified above that pargs < MAXMODEPARAMS
531 * checking for para[lcount] != '\0' is also wrong, since
532 * there is no place where para[lcount] is set!
533 * - Dianora
534 */
535
536 if (pargs != 0)
537 {
538 sptr = sendbuf;
539
540 for (lcount = 0; lcount < pargs; lcount++)
541 {
542 slen = ircsprintf(sptr, " %s", para[lcount]);
543 sptr += slen;
544 }
545
546 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
547 servername, chptr->chname, modebuf, sendbuf);
548 }
549
550 /* If this happens, its the result of a malformed SJOIN
551 * a remnant from the old persistent channel code. *sigh*
552 * Or it could be the result of a client just leaving
553 * and leaving us with a channel formed just as the client parts.
554 * - Dianora
555 */
556
557 if ((dlink_list_length(&chptr->members) == 0) && isnew)
558 {
559 destroy_channel(chptr);
560 return;
561 }
562
563 if (parv[4 + args][0] == '\0')
564 return;
565
566 /* relay the SJOIN to other servers */
567 DLINK_FOREACH(m, serv_list.head)
568 {
569 target_p = m->data;
570
571 if (target_p == client_p)
572 continue;
573
574 if (IsCapable(target_p, CAP_TS6))
575 sendto_one(target_p, "%s", uid_buf);
576 else
577 sendto_one(target_p, "%s", nick_buf);
578 }
579
580 if (HasID(source_p) && !keep_our_modes)
581 {
582 if (dlink_list_length(&chptr->banlist) > 0)
583 remove_ban_list(chptr, client_p, &chptr->banlist,
584 'b', NOCAPS);
585
586 if (dlink_list_length(&chptr->exceptlist) > 0)
587 remove_ban_list(chptr, client_p, &chptr->exceptlist,
588 'e', CAP_EX);
589
590 if (dlink_list_length(&chptr->invexlist) > 0)
591 remove_ban_list(chptr, client_p, &chptr->invexlist,
592 'I', CAP_IE);
593 clear_ban_cache(chptr);
594 }
595 }
596
597 /* set_final_mode
598 *
599 * inputs - channel mode
600 * - old channel mode
601 * output - NONE
602 * side effects - walk through all the channel modes turning off modes
603 * that were on in oldmode but aren't on in mode.
604 * Then walk through turning on modes that are on in mode
605 * but were not set in oldmode.
606 */
607 static void
608 set_final_mode(struct Mode *mode, struct Mode *oldmode)
609 {
610 const struct mode_letter *tab;
611 char *pbuf = parabuf;
612 int len;
613
614 *mbuf++ = '-';
615
616 for (tab = chan_modes; tab->letter; ++tab)
617 {
618 if ((tab->mode & oldmode->mode) &&
619 !(tab->mode & mode->mode))
620 *mbuf++ = tab->letter;
621 }
622
623 if (oldmode->limit != 0 && mode->limit == 0)
624 *mbuf++ = 'l';
625
626 if (oldmode->key[0] && !mode->key[0])
627 {
628 *mbuf++ = 'k';
629 len = ircsprintf(pbuf, "%s ", oldmode->key);
630 pbuf += len;
631 pargs++;
632 }
633
634 if (*(mbuf-1) == '-')
635 *(mbuf-1) = '+';
636 else
637 *mbuf++ = '+';
638
639 for (tab = chan_modes; tab->letter; ++tab)
640 {
641 if ((tab->mode & mode->mode) &&
642 !(tab->mode & oldmode->mode))
643 *mbuf++ = tab->letter;
644 }
645
646 if (mode->limit != 0 && oldmode->limit != mode->limit)
647 {
648 *mbuf++ = 'l';
649 len = ircsprintf(pbuf, "%d ", mode->limit);
650 pbuf += len;
651 pargs++;
652 }
653
654 if (mode->key[0] && strcmp(oldmode->key, mode->key))
655 {
656 *mbuf++ = 'k';
657 len = ircsprintf(pbuf, "%s ", mode->key);
658 pbuf += len;
659 pargs++;
660 }
661 if (*(mbuf-1) == '+')
662 *(mbuf-1) = '\0';
663 else
664 *mbuf = '\0';
665 }
666
667 /* remove_our_modes()
668 *
669 * inputs - pointer to channel to remove modes from
670 * - client pointer
671 * output - NONE
672 * side effects - Go through the local members, remove all their
673 * chanop modes etc., this side lost the TS.
674 */
675 static void
676 remove_our_modes(struct Channel *chptr, struct Client *source_p)
677 {
678 remove_a_mode(chptr, source_p, CHFL_CHANOP, 'o');
679 #ifdef HALFOPS
680 remove_a_mode(chptr, source_p, CHFL_HALFOP, 'h');
681 #endif
682 remove_a_mode(chptr, source_p, CHFL_VOICE, 'v');
683 }
684
685 /* remove_a_mode()
686 *
687 * inputs - pointer to channel
688 * - server or client removing the mode
689 * - mask o/h/v mask to be removed
690 * - flag o/h/v to be removed
691 * output - NONE
692 * side effects - remove ONE mode from all members of a channel
693 */
694 static void
695 remove_a_mode(struct Channel *chptr, struct Client *source_p,
696 int mask, char flag)
697 {
698 dlink_node *ptr;
699 struct Membership *ms;
700 char lmodebuf[MODEBUFLEN];
701 char *sp=sendbuf;
702 const char *lpara[MAXMODEPARAMS];
703 int count = 0;
704 int i;
705 int l;
706
707 mbuf = lmodebuf;
708 *mbuf++ = '-';
709 *sp = '\0';
710
711 DLINK_FOREACH(ptr, chptr->members.head)
712 {
713 ms = ptr->data;
714
715 if ((ms->flags & mask) == 0)
716 continue;
717
718 ms->flags &= ~mask;
719
720 lpara[count++] = ms->client_p->name;
721
722 *mbuf++ = flag;
723
724 if (count >= MAXMODEPARAMS)
725 {
726 for(i = 0; i < MAXMODEPARAMS; i++)
727 {
728 l = ircsprintf(sp, " %s", lpara[i]);
729 sp += l;
730 }
731
732 *mbuf = '\0';
733 sendto_channel_local(ALL_MEMBERS, 0, chptr,
734 ":%s MODE %s %s%s",
735 (IsHidden(source_p) ||
736 ConfigServerHide.hide_servers) ?
737 me.name : source_p->name,
738 chptr->chname, lmodebuf, sendbuf);
739 mbuf = lmodebuf;
740 *mbuf++ = '-';
741 count = 0;
742 sp = sendbuf;
743 *sp = '\0';
744 }
745 }
746
747 if (count != 0)
748 {
749 *mbuf = '\0';
750 for(i = 0; i < count; i++)
751 {
752 l = ircsprintf(sp, " %s", lpara[i]);
753 sp += l;
754 }
755 sendto_channel_local(ALL_MEMBERS, 0, chptr,
756 ":%s MODE %s %s%s",
757 (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
758 me.name : source_p->name,
759 chptr->chname, lmodebuf, sendbuf);
760 }
761 }
762
763 /* remove_ban_list()
764 *
765 * inputs - channel, source, list to remove, char of mode, caps required
766 * outputs - none
767 * side effects - given ban list is removed, modes are sent to local clients and
768 * non-ts6 servers linked through another uplink other than source_p
769 */
770 static void
771 remove_ban_list(struct Channel *chptr, struct Client *source_p,
772 dlink_list *list, char c, int cap)
773 {
774 char lmodebuf[MODEBUFLEN];
775 char lparabuf[IRCD_BUFSIZE];
776 struct Ban *banptr = NULL;
777 dlink_node *ptr = NULL;
778 dlink_node *next_ptr = NULL;
779 char *pbuf = NULL;
780 int count = 0;
781 int cur_len, mlen, plen;
782
783 pbuf = lparabuf;
784
785 cur_len = mlen = ircsprintf(lmodebuf, ":%s MODE %s -",
786 source_p->name, chptr->chname);
787 mbuf = lmodebuf + mlen;
788
789 DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
790 {
791 banptr = ptr->data;
792
793 plen = banptr->len + 4; /* another +b and "!@ " */
794 if (count >= MAXMODEPARAMS ||
795 (cur_len + 1 /* space between */ + (plen - 1)) > IRCD_BUFSIZE - 2)
796 {
797 /* NUL-terminate and remove trailing space */
798 *mbuf = *(pbuf - 1) = '\0';
799 sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s",
800 lmodebuf, lparabuf);
801 sendto_server(source_p, cap, CAP_TS6,
802 "%s %s", lmodebuf, lparabuf);
803
804 cur_len = mlen;
805 mbuf = lmodebuf + mlen;
806 pbuf = lparabuf;
807 count = 0;
808 }
809
810 *mbuf++ = c;
811 cur_len += plen;
812 pbuf += ircsprintf(pbuf, "%s!%s@%s ", banptr->name, banptr->username,
813 banptr->host);
814 ++count;
815
816 remove_ban(banptr, list);
817 }
818
819 *mbuf = *(pbuf - 1) = '\0';
820 sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", lmodebuf, lparabuf);
821 sendto_server(source_p, cap, CAP_TS6,
822 "%s %s", lmodebuf, lparabuf);
823 }
824
825 static struct Message sjoin_msgtab = {
826 "SJOIN", 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
827 {m_unregistered, m_ignore, ms_sjoin, m_ignore, m_ignore, m_ignore}
828 };
829
830 static void
831 module_init(void)
832 {
833 mod_add_cmd(&sjoin_msgtab);
834 }
835
836 static void
837 module_exit(void)
838 {
839 mod_del_cmd(&sjoin_msgtab);
840 }
841
842 struct module module_entry = {
843 .node = { NULL, NULL, NULL },
844 .name = NULL,
845 .version = "$Revision$",
846 .handle = NULL,
847 .modinit = module_init,
848 .modexit = module_exit,
849 .flags = MODULE_FLAG_CORE
850 };

Properties

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