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

Contents of /ircd-hybrid-7.2/modules/core/m_join.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 487 - (show annotations)
Wed Mar 1 10:54:20 2006 UTC (13 years, 11 months ago) by michael
File MIME type: text/x-chdr
File size: 21419 byte(s)
- Fixed bug where "JOIN #keyedchan1,#keyedchan2 key1,key2" wouldn't work.
  Reported by ThaPrince

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

Properties

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

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