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: 1178
Committed: Mon Aug 15 08:11:31 2011 UTC (12 years, 7 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/core/m_sjoin.c
File size: 21060 byte(s)
Log Message:
- Cleanup and restore older parts of the irc-command parser.
  Gives back ability to specify maximum amount of parameters
  that are processed within a command.

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

Properties

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