ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_sjoin.c
Revision: 1155
Committed: Tue Aug 9 20:27:45 2011 UTC (14 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/core/m_sjoin.c
File size: 21303 byte(s)
Log Message:
- recreate "trunk"

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

Properties

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