ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_sjoin.c
Revision: 34
Committed: Sun Oct 2 21:05:51 2005 UTC (18 years, 6 months ago) by lusky
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_sjoin.c
File size: 22040 byte(s)
Log Message:
create 7.2 branch, we can move/rename it as needed.


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

Properties

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