ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/core/m_join.c
Revision: 488
Committed: Wed Mar 1 12:40:31 2006 UTC (18 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 19633 byte(s)
Log Message:
- Rewrote m_join(). This was mainly done to fix some bug that can be easily abused.
  Details about this bug have been given on IRC.

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

Properties

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