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

# User Rev Content
1 adx 30 /*
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 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26 michael 1011 #include "list.h"
27 adx 30 #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 michael 1309 #include "conf.h"
39 michael 1243 #include "s_misc.h"
40 adx 30
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 michael 885
55 adx 30 /* 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 michael 632 struct Channel *chptr = NULL;
72     struct Client *target_p = NULL;
73 adx 30 time_t newts;
74     time_t oldts;
75     time_t tstosend;
76 michael 632 struct Mode mode, *oldmode;
77 adx 30 int args = 0;
78 michael 1243 char keep_our_modes = 1;
79     char keep_new_modes = 1;
80     char have_many_nicks = 0;
81 adx 30 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 michael 632 int isnew = 0;
88 adx 30 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 michael 632 if (!check_channel_name(parv[2], 0))
105     {
106 michael 1618 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
107 michael 632 "*** Too long or invalid channel name from %s: %s",
108     client_p->name, parv[2]);
109 adx 30 return;
110 michael 632 }
111 adx 30
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 michael 632 for (s = parv[3]; *s; ++s)
122 adx 30 {
123 michael 632 switch (*s)
124 adx 30 {
125 michael 1937 case 'c':
126     mode.mode |= MODE_NOCTRL;
127     break;
128 adx 30 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 michael 1167 case 'r':
147     mode.mode |= MODE_REGISTERED;
148     break;
149 michael 1150 case 'O':
150     mode.mode |= MODE_OPERONLY;
151     break;
152     case 'S':
153     mode.mode |= MODE_SSLONLY;
154     break;
155 adx 30 case 'k':
156     strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
157     args++;
158 michael 632
159     if (parc < 5 + args)
160 adx 30 return;
161     break;
162     case 'l':
163     mode.limit = atoi(parv[4 + args]);
164     args++;
165 michael 632
166     if (parc < 5 + args)
167 adx 30 return;
168     break;
169     }
170     }
171    
172 michael 632 if ((chptr = hash_find_channel(parv[2])) == NULL)
173     {
174     isnew = 1;
175     chptr = make_channel(parv[2]);
176     }
177    
178 adx 30 parabuf[0] = '\0';
179 michael 632 oldts = chptr->channelts;
180 adx 30 oldmode = &chptr->mode;
181    
182     if (ConfigFileEntry.ignore_bogus_ts)
183     {
184     if (newts < 800000000)
185     {
186 michael 1618 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
187 adx 30 "*** 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 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr,
199 adx 30 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to 0",
200     me.name, chptr->chname, chptr->chname, (unsigned long)oldts);
201 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
202 adx 30 "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 michael 1243 keep_our_modes = 0;
216 adx 30 chptr->channelts = tstosend = newts;
217     }
218     else
219     {
220 michael 1243 keep_new_modes = 0;
221 adx 30 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 michael 873
242 michael 1203 if (chptr->topic[0])
243 michael 873 {
244 michael 1751 set_channel_topic(chptr, "", "", 0, 0);
245 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s TOPIC %s :",
246 michael 873 (IsHidden(source_p) ||
247     ConfigServerHide.hide_servers) ?
248     me.name : source_p->name, chptr->chname);
249     }
250    
251 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr,
252 adx 30 ":%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 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s %s",
262 adx 30 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 michael 1793 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 adx 30 nick_ptr = nick_buf + buflen;
279    
280 michael 1793 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 adx 30 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 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
291 adx 30 "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 michael 1243 int valid_mode = 1;
316 adx 30 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 michael 1243 valid_mode = 0;
338 adx 30 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 michael 1474 sendto_server(client_p, 0, CAP_TS6, "%s", nick_buf);
401 adx 30
402 michael 1793 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 adx 30 nick_ptr = nick_buf + buflen;
406     }
407 michael 885
408 michael 1793 nick_ptr += sprintf(nick_ptr, "%s%s ", nick_prefix, target_p->name);
409 adx 30
410     if ((uid_ptr - uid_buf + len_uid) > (IRCD_BUFSIZE - 2))
411     {
412 michael 1474 sendto_server(client_p, CAP_TS6, 0, "%s", uid_buf);
413 adx 30
414 michael 1793 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 adx 30 uid_ptr = uid_buf + buflen;
418     }
419    
420 michael 1793 uid_ptr += sprintf(uid_ptr, "%s%s ", uid_prefix, ID(target_p));
421 adx 30
422     if (!IsMember(target_p, chptr))
423     {
424     add_user_to_channel(chptr, target_p, fl, !have_many_nicks);
425 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
426 adx 30 target_p->name, target_p->username,
427     target_p->host, chptr->chname);
428 michael 1734 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 adx 30 }
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 michael 1793 slen = sprintf(sptr, " %s", para[lcount]); /* see? */
456 adx 30 sptr += slen; /* ready for next */
457     }
458 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
459 adx 30 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 michael 1793 slen = sprintf(sptr, " %s", para[lcount]);
480 adx 30 sptr += slen;
481     }
482 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
483 adx 30 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 michael 1793 slen = sprintf(sptr, " %s", para[lcount]);
505 adx 30 sptr += slen;
506     }
507 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
508 adx 30 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 michael 1793 slen = sprintf(sptr, " %s", para[lcount]);
550 adx 30 sptr += slen;
551     }
552    
553 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
554 adx 30 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 michael 1175 const struct mode_letter *tab;
618 adx 30 char *pbuf = parabuf;
619     int len;
620    
621     *mbuf++ = '-';
622    
623 michael 1175 for (tab = chan_modes; tab->letter; ++tab)
624 adx 30 {
625 michael 1175 if ((tab->mode & oldmode->mode) &&
626     !(tab->mode & mode->mode))
627     *mbuf++ = tab->letter;
628 adx 30 }
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 michael 1793 len = sprintf(pbuf, "%s ", oldmode->key);
637 adx 30 pbuf += len;
638     pargs++;
639     }
640    
641     if (*(mbuf-1) == '-')
642     *(mbuf-1) = '+';
643     else
644     *mbuf++ = '+';
645    
646 michael 1175 for (tab = chan_modes; tab->letter; ++tab)
647 adx 30 {
648 michael 1175 if ((tab->mode & mode->mode) &&
649     !(tab->mode & oldmode->mode))
650     *mbuf++ = tab->letter;
651 adx 30 }
652    
653     if (mode->limit != 0 && oldmode->limit != mode->limit)
654     {
655     *mbuf++ = 'l';
656 michael 1793 len = sprintf(pbuf, "%d ", mode->limit);
657 adx 30 pbuf += len;
658     pargs++;
659     }
660    
661     if (mode->key[0] && strcmp(oldmode->key, mode->key))
662     {
663     *mbuf++ = 'k';
664 michael 1793 len = sprintf(pbuf, "%s ", mode->key);
665 adx 30 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 michael 1793 l = sprintf(sp, " %s", lpara[i]);
736 adx 30 sp += l;
737     }
738    
739     *mbuf = '\0';
740 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr,
741 adx 30 ":%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 michael 1793 l = sprintf(sp, " %s", lpara[i]);
760 adx 30 sp += l;
761     }
762 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr,
763 adx 30 ":%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 michael 1793 cur_len = mlen = sprintf(lmodebuf, ":%s MODE %s -",
793     source_p->name, chptr->chname);
794 adx 30 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 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s",
807 adx 30 lmodebuf, lparabuf);
808 michael 1474 sendto_server(source_p, cap, CAP_TS6,
809 adx 30 "%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 michael 1793 pbuf += sprintf(pbuf, "%s!%s@%s ", banptr->name, banptr->username,
820     banptr->host);
821 adx 30 ++count;
822    
823     remove_ban(banptr, list);
824     }
825    
826     *mbuf = *(pbuf - 1) = '\0';
827 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", lmodebuf, lparabuf);
828 michael 1474 sendto_server(source_p, cap, CAP_TS6,
829 adx 30 "%s %s", lmodebuf, lparabuf);
830     }
831 michael 1230
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