ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/core/m_sjoin.c
Revision: 885
Committed: Wed Oct 31 18:09:24 2007 UTC (18 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 21163 byte(s)
Log Message:
- Removed LazyLinks in 7.2 to stop people from asking why we keep
  broken code for half a decade. LL will be implemented in a smarter
  fashion in due time

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

Properties

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