ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_join.c
Revision: 393
Committed: Fri Feb 3 15:50:47 2006 UTC (18 years, 2 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_join.c
File size: 21577 byte(s)
Log Message:
- Backported max_chans_per_user fix from HEAD

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * m_join.c: Joins 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 "common.h" /* bleah */
32     #include "hash.h"
33     #include "irc_string.h"
34     #include "sprintf_irc.h"
35     #include "ircd.h"
36     #include "list.h"
37     #include "numeric.h"
38     #include "send.h"
39     #include "s_serv.h"
40     #include "s_conf.h"
41     #include "msg.h"
42     #include "parse.h"
43     #include "modules.h"
44    
45    
46     struct entity
47     {
48     struct Channel *chptr;
49     char *key;
50     int flags;
51     };
52    
53 michael 393 static struct entity targets[IRCD_BUFSIZE];
54 adx 30 static int ntargets, join_0;
55    
56     static int build_target_list(struct Client *, struct Client *, char *, char *);
57     static int is_target(struct Channel *);
58    
59     static void m_join(struct Client *, struct Client *, int, char **);
60     static void ms_join(struct Client *, struct Client *, int, char **);
61     static void do_join_0(struct Client *client_p, struct Client *source_p);
62    
63     static void set_final_mode(struct Mode *, struct Mode *);
64     static void remove_our_modes(struct Channel *, struct Client *);
65     static void remove_a_mode(struct Channel *, struct Client *, int, char);
66    
67     static char modebuf[MODEBUFLEN];
68     static char parabuf[MODEBUFLEN];
69     static char sendbuf[MODEBUFLEN];
70     static char *mbuf;
71    
72     struct Message join_msgtab = {
73     "JOIN", 0, 0, 2, 0, MFLG_SLOW, 0,
74     {m_unregistered, m_join, ms_join, m_ignore, m_join, m_ignore}
75     };
76    
77     #ifndef STATIC_MODULES
78    
79     void
80     _modinit(void)
81     {
82     mod_add_cmd(&join_msgtab);
83     }
84    
85     void
86     _moddeinit(void)
87     {
88     mod_del_cmd(&join_msgtab);
89     }
90    
91 knight 31 const char *_version = "$Revision$";
92 adx 30 #endif
93    
94     /* m_join()
95     * parv[0] = sender prefix
96     * parv[1] = channel
97     * parv[2] = channel password (key)
98     */
99     static void
100     m_join(struct Client *client_p, struct Client *source_p,
101     int parc, char *parv[])
102     {
103     struct Channel *chptr = NULL;
104     char *key = NULL;
105     int i, a;
106     unsigned int flags = 0;
107     int successful_join_count = 0; /* Number of channels successfully joined */
108    
109     if (*parv[1] == '\0')
110     {
111     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
112     me.name, source_p->name, "JOIN");
113     return;
114     }
115    
116     build_target_list(client_p, source_p, parv[1], ((parc > 2) ? parv[2] : NULL));
117    
118     if ((a = (join_0 >= 0) ? join_0 : 0))
119     do_join_0(client_p, source_p);
120    
121     for (; a < ntargets; a++)
122     {
123     chptr = targets[a].chptr;
124     key = targets[a].key;
125     flags = targets[a].flags;
126    
127     if (IsMember(source_p, chptr))
128     continue;
129    
130     if (!IsOper(source_p))
131     check_spambot_warning(source_p, chptr->chname);
132    
133     /*
134     * can_join checks for +i key, bans.
135     */
136     if ((i = can_join(source_p, chptr, key)))
137     {
138     sendto_one(source_p, form_str(i), me.name, source_p->name, chptr->chname);
139     continue;
140     }
141    
142     ++successful_join_count;
143    
144     /* add the user to the channel */
145     add_user_to_channel(chptr, source_p, flags, YES);
146    
147     /*
148     ** Set timestamp if appropriate, and propagate
149     */
150     if (flags & CHFL_CHANOP)
151     {
152     chptr->channelts = CurrentTime;
153     chptr->mode.mode |= MODE_TOPICLIMIT;
154     chptr->mode.mode |= MODE_NOPRIVMSGS;
155    
156     sendto_server(client_p, source_p, chptr, CAP_TS6, NOCAPS, LL_ICLIENT,
157     ":%s SJOIN %lu %s +nt :@%s",
158     me.id, (unsigned long)chptr->channelts,
159     chptr->chname, source_p->id);
160     sendto_server(client_p, source_p, chptr, NOCAPS, CAP_TS6, LL_ICLIENT,
161     ":%s SJOIN %lu %s +nt :@%s",
162     me.name, (unsigned long)chptr->channelts,
163     chptr->chname, parv[0]);
164     /*
165     * notify all other users on the new channel
166     */
167     /* XXX just exactly who is going to be =on= this new channel
168     * other than just the creator at this time? ? ?
169     */
170     sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s JOIN :%s",
171     source_p->name, source_p->username,
172     source_p->host, chptr->chname);
173    
174     sendto_channel_local(ALL_MEMBERS, NO, chptr,
175     ":%s MODE %s +nt",
176     me.name, chptr->chname);
177     }
178     else
179     {
180     sendto_server(client_p, source_p, chptr, CAP_TS6, NOCAPS, LL_ICLIENT,
181     ":%s JOIN %lu %s +",
182     source_p->id, (unsigned long)chptr->channelts,
183     chptr->chname);
184     sendto_server(client_p, source_p, chptr, NOCAPS, CAP_TS6, LL_ICLIENT,
185     ":%s SJOIN %lu %s + :%s",
186     me.name, (unsigned long)chptr->channelts,
187     chptr->chname, source_p->name);
188    
189     sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s JOIN :%s",
190     source_p->name, source_p->username,
191     source_p->host, chptr->chname);
192     }
193    
194     del_invite(chptr, source_p);
195    
196     if (chptr->topic != NULL)
197     {
198     sendto_one(source_p, form_str(RPL_TOPIC), me.name,
199     source_p->name, chptr->chname, chptr->topic);
200    
201     sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
202     me.name, source_p->name, chptr->chname,
203     chptr->topic_info, chptr->topic_time);
204     }
205    
206     channel_member_names(source_p, chptr, 1);
207    
208     if (successful_join_count != 0)
209     source_p->localClient->last_join_time = CurrentTime;
210     }
211     }
212    
213     /* ms_join()
214     *
215     * inputs - parv[0] = uid
216     * parv[1] = ts
217     * parv[2] = channel name
218     * parv[3] = modes
219     * output - none
220     * side effects - handles remote JOIN's sent by servers. In TSora
221     * remote clients are joined using SJOIN, hence a
222     * JOIN sent by a server on behalf of a client is an error.
223     * here, the initial code is in to take an extra parameter
224     * and use it for the TimeStamp on a new channel.
225     */
226     static void
227     ms_join(struct Client *client_p, struct Client *source_p,
228     int parc, char *parv[])
229     {
230     struct Channel *chptr;
231     time_t newts;
232     time_t oldts;
233     static struct Mode mode, *oldmode;
234     int args = 0;
235     int keep_our_modes = 1;
236     int keep_new_modes = 1;
237     int isnew;
238     char *s;
239     const char *servername;
240    
241     if ((parv[1][0] == '0') && (parv[1][1] == '\0') && parc == 2)
242     {
243     do_join_0(client_p, source_p);
244     return;
245     }
246    
247     if (parc < 4)
248     return;
249    
250     if (*parv[2] == '&')
251     return;
252    
253     if (!check_channel_name(parv[2]))
254     return;
255    
256     mbuf = modebuf;
257     mode.mode = mode.limit = 0;
258     mode.key[0] = '\0';
259    
260     s = parv[3];
261     while (*s)
262     {
263     switch (*(s++))
264     {
265     case 't':
266     mode.mode |= MODE_TOPICLIMIT;
267     break;
268     case 'n':
269     mode.mode |= MODE_NOPRIVMSGS;
270     break;
271     case 's':
272     mode.mode |= MODE_SECRET;
273     break;
274     case 'm':
275     mode.mode |= MODE_MODERATED;
276     break;
277     case 'i':
278     mode.mode |= MODE_INVITEONLY;
279     break;
280     case 'p':
281     mode.mode |= MODE_PRIVATE;
282     break;
283     case 'k':
284     if (parc < 5+args)
285     return;
286    
287     strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
288     args++;
289     break;
290     case 'l':
291     if (parc < 5+args)
292     return;
293    
294     mode.limit = atoi(parv[4 + args]);
295     args++;
296     break;
297     }
298     }
299    
300     if ((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
301     return; /* channel name too long? */
302    
303     newts = atol(parv[1]);
304     oldts = chptr->channelts;
305     oldmode = &chptr->mode;
306    
307     if (ConfigFileEntry.ignore_bogus_ts)
308     {
309     if (newts < 800000000)
310     {
311     sendto_realops_flags(UMODE_DEBUG, L_ALL,
312     "*** Bogus TS %lu on %s ignored from %s",
313     (unsigned long)newts, chptr->chname,
314     client_p->name);
315    
316     newts = (oldts == 0) ? 0 : 800000000;
317     }
318     }
319     else
320     {
321     if (!newts && !isnew && oldts)
322     {
323     sendto_channel_local(ALL_MEMBERS, NO, chptr,
324     ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to 0",
325     me.name, chptr->chname, chptr->chname, (unsigned long)oldts);
326     sendto_realops_flags(UMODE_ALL, L_ALL,
327     "Server %s changing TS on %s from %lu to 0",
328     source_p->name, chptr->chname, (unsigned long)oldts);
329     }
330     }
331    
332     if (isnew)
333     chptr->channelts = newts;
334     else if (newts == 0 || oldts == 0)
335     chptr->channelts = 0;
336     else if (newts == oldts)
337     ;
338     else if (newts < oldts)
339     {
340     keep_our_modes = NO;
341     chptr->channelts = newts;
342     }
343     else
344     keep_new_modes = NO;
345    
346     if (!keep_new_modes)
347     mode = *oldmode;
348     else if (keep_our_modes)
349     {
350     mode.mode |= oldmode->mode;
351     if (oldmode->limit > mode.limit)
352     mode.limit = oldmode->limit;
353     if (strcmp(mode.key, oldmode->key) < 0)
354     strcpy(mode.key, oldmode->key);
355     }
356    
357     set_final_mode(&mode, oldmode);
358     chptr->mode = mode;
359    
360     /* Lost the TS, other side wins, so remove modes on this side */
361     if (!keep_our_modes)
362     {
363     remove_our_modes(chptr, source_p);
364     sendto_channel_local(ALL_MEMBERS, NO, chptr,
365     ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to %lu",
366     me.name, chptr->chname, chptr->chname,
367     (unsigned long)oldts, (unsigned long)newts);
368     }
369    
370     if (*modebuf != '\0')
371     {
372     servername = (ConfigServerHide.hide_servers || IsHidden(source_p)) ?
373     me.name : source_p->name;
374    
375     /* This _SHOULD_ be to ALL_MEMBERS
376     * It contains only +imnpstlk, etc */
377     sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s %s %s",
378     servername, chptr->chname, modebuf, parabuf);
379     }
380    
381     if (!IsMember(source_p, chptr))
382     {
383     add_user_to_channel(chptr, source_p, 0, YES);
384     sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s JOIN :%s",
385     source_p->name, source_p->username,
386     source_p->host, chptr->chname);
387     }
388    
389     sendto_server(client_p, NULL, chptr, CAP_TS6, NOCAPS, NOFLAGS,
390     ":%s JOIN %lu %s +",
391     ID(source_p), (unsigned long)chptr->channelts, chptr->chname);
392     sendto_server(client_p, NULL, chptr, NOCAPS, CAP_TS6, NOFLAGS,
393     ":%s SJOIN %lu %s + :%s",
394     source_p->servptr->name, (unsigned long)chptr->channelts,
395     chptr->chname, source_p->name);
396     }
397    
398     /* do_join_0()
399     *
400     * inputs - pointer to client doing join 0
401     * output - NONE
402     * side effects - Use has decided to join 0. This is legacy
403     * from the days when channels were numbers not names. *sigh*
404     * There is a bunch of evilness necessary here due to
405     * anti spambot code.
406     */
407     static void
408     do_join_0(struct Client *client_p, struct Client *source_p)
409     {
410     struct Channel *chptr = NULL;
411     dlink_node *ptr, *ptr_next;
412    
413     if (source_p->channel.head != NULL &&
414     MyConnect(source_p) && !IsOper(source_p))
415     check_spambot_warning(source_p, NULL);
416    
417     DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->channel.head)
418     {
419     chptr = ((struct Membership *)ptr->data)->chptr;
420    
421     /* if the last occurance of this chan is before a 0, leave */
422     if (is_target(chptr) < join_0)
423     {
424     sendto_server(client_p, NULL, chptr, CAP_TS6, NOCAPS, NOFLAGS,
425     ":%s PART %s", ID(source_p), chptr->chname);
426     sendto_server(client_p, NULL, chptr, NOCAPS, CAP_TS6, NOFLAGS,
427     ":%s PART %s", source_p->name, chptr->chname);
428     sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s PART %s",
429     source_p->name, source_p->username,
430     source_p->host, chptr->chname);
431     remove_user_from_channel(ptr->data);
432     }
433     }
434     }
435    
436     /* build_target_list()
437     *
438     * inputs - pointer to given client_p (server)
439     * - pointer to given source (oper/client etc.)
440     * - pointer to list of channels
441     * - pointer to list of keys
442     * output - number of valid entities
443     * side effects - targets list is modified to contain a list of
444     * pointers to channels. display whatever errors
445     * that result from a join attempt to the user.
446     *
447     */
448     static int
449     build_target_list(struct Client *client_p, struct Client *source_p,
450     char *channels, char *keys)
451     {
452     int error_reported, flags = 0;
453     char *p, *p2, *chan, *key = keys;
454     struct Channel *chptr = NULL;
455    
456     ntargets = error_reported = 0;
457     join_0 = -1;
458    
459     for (chan = strtoken(&p, channels, ","); chan;
460     key = (key) ? strtoken(&p2, keys, ",") : NULL,
461     chan = strtoken(&p, NULL, ","))
462     {
463     if (!check_channel_name(chan))
464     {
465     sendto_one(source_p, form_str(ERR_BADCHANNAME),
466     me.name, source_p->name, chan);
467     continue;
468     }
469    
470     if (*chan == '0' && !atoi(chan))
471     {
472     targets[ntargets].chptr = NULL;
473     targets[ntargets].key = NULL;
474     targets[ntargets++].flags = 0;
475    
476     join_0 = ntargets;
477     continue;
478     }
479     else if (!IsChanPrefix(*chan))
480     {
481     sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
482     me.name, source_p->name, chan);
483     continue;
484     }
485    
486     if (ConfigChannel.disable_local_channels && (*chan == '&'))
487     {
488     sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
489     me.name, source_p->name, chan);
490     continue;
491     }
492    
493 michael 100 if (strlen(chan) > LOCAL_CHANNELLEN)
494 adx 30 {
495     sendto_one(source_p, form_str(ERR_BADCHANNAME),
496     me.name, source_p->name, chan);
497     continue;
498     }
499    
500     if (!IsExemptResv(source_p) &&
501     !(IsOper(source_p) && ConfigFileEntry.oper_pass_resv) &&
502     (!hash_find_resv(chan) == ConfigChannel.restrict_channels))
503     {
504     sendto_one(source_p, form_str(ERR_BADCHANNAME),
505     me.name, source_p->name, chan);
506     sendto_realops_flags(UMODE_SPY, L_ALL,
507     "User %s (%s@%s) is attempting to join locally juped channel %s",
508     source_p->name, source_p->username, source_p->host, chan);
509     continue;
510     }
511    
512 michael 393 if ((dlink_list_length(&source_p->channel)+ntargets >= ConfigChannel.max_chans_per_user) &&
513     (!IsOper(source_p) || (dlink_list_length(&source_p->channel)+ntargets >=
514 adx 30 ConfigChannel.max_chans_per_user * 3)))
515     {
516     if (!error_reported++)
517     sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
518     me.name, source_p->name, chan);
519     continue;
520     }
521    
522     if ((chptr = hash_find_channel(chan)) != NULL)
523     {
524     if (splitmode && !IsOper(source_p) && (*chan != '&') &&
525     ConfigChannel.no_join_on_split)
526     {
527     sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
528     me.name, source_p->name, chan);
529     continue;
530     }
531    
532     if (dlink_list_length(&chptr->members) == 0)
533     flags = CHFL_CHANOP;
534     else
535     flags = 0;
536     }
537     else
538     {
539     if (splitmode && !IsOper(source_p) && (*chan != '&') &&
540     (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split))
541     {
542     sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
543     me.name, source_p->name, chan);
544     continue;
545     }
546    
547     flags = CHFL_CHANOP;
548     if (!ServerInfo.hub)
549     {
550     if ((*chan != '&') && uplink && IsCapable(uplink, CAP_LL))
551     {
552     sendto_one(uplink, ":%s CBURST %s %s %s",
553     me.name, chan, source_p->name, key ? key : "");
554     continue;
555     }
556     }
557    
558     if ((chptr = get_or_create_channel(source_p, chan, NULL)) == NULL)
559     {
560     sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
561     me.name, source_p->name, chan);
562     continue;
563     }
564     }
565    
566     if (is_target(chptr))
567     continue;
568    
569     targets[ntargets].chptr = chptr;
570     targets[ntargets].key = key;
571     targets[ntargets++].flags = flags;
572     }
573    
574     return ((ntargets) ? 1 : 0);
575     }
576    
577     /* is_target()
578     *
579     * inputs - channel to check
580     * output - YES if duplicate pointer in table, NO if not.
581     * note, this does the canonize using pointers
582     * side effects - NONE
583     */
584     static int
585     is_target(struct Channel *chptr)
586     {
587     int i;
588    
589     /*
590     * we step through this backwards for do_join_0()s sake.
591     * if the returned value is > join_0 (the highest 0 in the targets)
592     * we know they are supposed to stay in that channel.
593     */
594     for (i = ntargets-1; i >=0; i--)
595     {
596     if (targets[i].chptr == chptr)
597     return i;
598     }
599    
600     return 0;
601     }
602    
603     /* set_final_mode()
604     *
605     * inputs - pointer to mode to setup
606     * - pointer to old mode
607     * output - NONE
608     * side effects -
609     */
610     static const struct mode_letter
611     {
612     unsigned int mode;
613     unsigned char letter;
614     } flags[] = {
615     { MODE_NOPRIVMSGS, 'n' },
616     { MODE_TOPICLIMIT, 't' },
617     { MODE_SECRET, 's' },
618     { MODE_MODERATED, 'm' },
619     { MODE_INVITEONLY, 'i' },
620     { MODE_PRIVATE, 'p' },
621     { 0, '\0' }
622     };
623    
624     static void
625     set_final_mode(struct Mode *mode, struct Mode *oldmode)
626     {
627     char *pbuf = parabuf;
628     int what = 0;
629     int len;
630     int i;
631    
632     for (i = 0; flags[i].letter; i++)
633     {
634     if ((flags[i].mode & mode->mode) &&
635     !(flags[i].mode & oldmode->mode))
636     {
637     if (what != 1)
638     {
639     *mbuf++ = '+';
640     what = 1;
641     }
642     *mbuf++ = flags[i].letter;
643     }
644     }
645    
646     for (i = 0; flags[i].letter; i++)
647     {
648     if ((flags[i].mode & oldmode->mode) &&
649     !(flags[i].mode & mode->mode))
650     {
651     if (what != -1)
652     {
653     *mbuf++ = '-';
654     what = -1;
655     }
656     *mbuf++ = flags[i].letter;
657     }
658     }
659    
660     if (oldmode->limit != 0 && mode->limit == 0)
661     {
662     if (what != -1)
663     {
664     *mbuf++ = '-';
665     what = -1;
666     }
667     *mbuf++ = 'l';
668     }
669    
670     if (oldmode->key[0] && !mode->key[0])
671     {
672     if (what != -1)
673     {
674     *mbuf++ = '-';
675     what = -1;
676     }
677     *mbuf++ = 'k';
678     len = ircsprintf(pbuf, "%s ", oldmode->key);
679     pbuf += len;
680     }
681    
682     if (mode->limit != 0 && oldmode->limit != mode->limit)
683     {
684     if (what != 1)
685     {
686     *mbuf++ = '+';
687     what = 1;
688     }
689     *mbuf++ = 'l';
690     len = ircsprintf(pbuf, "%d ", mode->limit);
691     pbuf += len;
692     }
693    
694     if (mode->key[0] && strcmp(oldmode->key, mode->key))
695     {
696     if (what != 1)
697     {
698     *mbuf++ = '+';
699     what = 1;
700     }
701     *mbuf++ = 'k';
702     len = ircsprintf(pbuf, "%s ", mode->key);
703     pbuf += len;
704     }
705     *mbuf = '\0';
706     }
707    
708     /* remove_our_modes()
709     *
710     * inputs - pointer to channel to remove modes from
711     * - client pointer
712     * output - NONE
713     * side effects - Go through the local members, remove all their
714     * chanop modes etc., this side lost the TS.
715     */
716     static void
717     remove_our_modes(struct Channel *chptr, struct Client *source_p)
718     {
719     remove_a_mode(chptr, source_p, CHFL_CHANOP, 'o');
720     #ifdef HALFOPS
721     remove_a_mode(chptr, source_p, CHFL_HALFOP, 'h');
722     #endif
723     remove_a_mode(chptr, source_p, CHFL_VOICE, 'v');
724     }
725    
726     /* remove_a_mode()
727     *
728     * inputs -
729     * output - NONE
730     * side effects - remove ONE mode from a channel
731     */
732     static void
733     remove_a_mode(struct Channel *chptr, struct Client *source_p,
734     int mask, char flag)
735     {
736     dlink_node *ptr;
737     struct Membership *ms;
738     char lmodebuf[MODEBUFLEN];
739     const char *lpara[MAXMODEPARAMS];
740     int count = 0;
741     int lcount;
742    
743     mbuf = lmodebuf;
744     *mbuf++ = '-';
745    
746     for (lcount = 0; lcount < MAXMODEPARAMS; lcount++)
747     lpara[lcount] = "";
748     sendbuf[0] = '\0';
749    
750     DLINK_FOREACH(ptr, chptr->members.head)
751     {
752     ms = ptr->data;
753    
754     if ((ms->flags & mask) == 0)
755     continue;
756    
757     ms->flags &= ~mask;
758    
759     lpara[count++] = ms->client_p->name;
760    
761     *mbuf++ = flag;
762    
763     if (count >= MAXMODEPARAMS)
764     {
765     for (lcount = 0; lcount < MAXMODEPARAMS; lcount++)
766     {
767     if (*lpara[lcount] == '\0')
768     break;
769    
770     strlcat(sendbuf, " ", sizeof(sendbuf));
771     strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
772     lpara[lcount] = "";
773     }
774    
775     *mbuf = '\0';
776     sendto_channel_local(ALL_MEMBERS, NO, chptr,
777     ":%s MODE %s %s%s",
778     (IsHidden(source_p) ||
779     ConfigServerHide.hide_servers) ?
780     me.name : source_p->name,
781     chptr->chname, lmodebuf, sendbuf);
782     mbuf = lmodebuf;
783     *mbuf++ = '-';
784     count = 0;
785     sendbuf[0] = '\0';
786     }
787     }
788    
789     if (count != 0)
790     {
791     *mbuf = '\0';
792     for (lcount = 0; lcount < MAXMODEPARAMS; lcount++)
793     {
794     if (*lpara[lcount] == '\0')
795     break;
796    
797     strlcat(sendbuf, " ", sizeof(sendbuf));
798     strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
799     }
800     sendto_channel_local(ALL_MEMBERS, NO, chptr,
801     ":%s MODE %s %s%s",
802     (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
803     me.name : source_p->name,
804     chptr->chname, lmodebuf, sendbuf);
805     }
806     }
807    

Properties

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