ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_sjoin.c
Revision: 1793
Committed: Sun Mar 31 14:06:08 2013 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 21359 byte(s)
Log Message:
- Replaced all occurrences of ircsprintf with sprintf/snprintf
  and killed sprintf_irc.(c|h)

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

Properties

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