ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_sjoin.c
Revision: 1751
Committed: Wed Jan 16 18:30:52 2013 UTC (13 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 21342 byte(s)
Log Message:
- Forward-port -r1750 [IMPORTANT: nick and topic lengths are now configurable
  via ircd.conf. A max_nick_length, as well as a max_topic_length configuration
  option can now be found in the serverinfo{} block]
- OpenSSL 0.9.8s and higher is now required in order to enable ssl support

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

Properties

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