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: 1029
Committed: Sun Nov 8 13:10:50 2009 UTC (14 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/modules/core/m_sjoin.c
File size: 21144 byte(s)
Log Message:
- branch off trunk to create 7.3 branch

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

Properties

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