/[svn]/ircd-hybrid/modules/core/m_sjoin.c
ViewVC logotype

Annotation of /ircd-hybrid/modules/core/m_sjoin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 632 - (hide annotations)
Thu Jun 1 10:53:00 2006 UTC (15 years ago) by michael
Original Path: ircd-hybrid-7.2/modules/core/m_sjoin.c
File MIME type: text/x-chdr
File size: 22222 byte(s)
- Added channel::disable_fake_channels which disallows creation of channels
  that have ascii 2, 3, 31 and 160 in their names.
- Minor improvements and cleanups to channel name validation routines
  backported from 7.3

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

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28