ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/core/m_join.c
Revision: 393
Committed: Fri Feb 3 15:50:47 2006 UTC (18 years, 1 month 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

# Content
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 *, 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 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 if (strlen(chan) > LOCAL_CHANNELLEN)
494 {
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 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 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