ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/releases/8.1.12/modules/core/m_join.c
Revision: 1219
Committed: Sun Sep 18 09:02:38 2011 UTC (15 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/core/m_join.c
File size: 18634 byte(s)
Log Message:
- Start cleaning up macros in client.h. Replace several ClientHasSomeCoolFlag()
with simple HasFlag/HasUMode macros.

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

Properties

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