]> jfr.im git - irc/rqf/shadowircd.git/blame - src/channel.c
Fix a couple typos.
[irc/rqf/shadowircd.git] / src / channel.c
CommitLineData
212380e3 1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * channel.c: Controls channels.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
83294285 24 * $Id: channel.c 3580 2007-11-07 23:45:14Z jilles $
212380e3 25 */
26
27#include "stdinc.h"
212380e3 28#include "channel.h"
fba62b01 29#include "chmode.h"
212380e3 30#include "client.h"
31#include "common.h"
32#include "hash.h"
33#include "hook.h"
13ae2f4b 34#include "match.h"
212380e3 35#include "ircd.h"
36#include "numeric.h"
37#include "s_serv.h" /* captab */
38#include "s_user.h"
39#include "send.h"
40#include "whowas.h"
41#include "s_conf.h" /* ConfigFileEntry, ConfigChannel */
42#include "s_newconf.h"
d3455e2c 43#include "logger.h"
3472ff3f 44#include "packet.h"
212380e3 45
9813daca 46struct config_channel_entry ConfigChannel;
1a218aaf 47rb_dlink_list global_channel_list;
5475a932
VY
48static rb_bh *channel_heap;
49static rb_bh *ban_heap;
50static rb_bh *topic_heap;
51static rb_bh *member_heap;
52
212380e3 53static int channel_capabs[] = { CAP_EX, CAP_IE,
54 CAP_SERVICE,
55 CAP_TS6
56};
57
58#define NCHCAPS (sizeof(channel_capabs)/sizeof(int))
59#define NCHCAP_COMBOS (1 << NCHCAPS)
60
61static struct ChCapCombo chcap_combos[NCHCAP_COMBOS];
62
63static void free_topic(struct Channel *chptr);
64
65static int h_can_join;
67b90240
JH
66static int h_can_create_channel;
67static int h_channel_join;
212380e3 68
69/* init_channels()
70 *
71 * input -
72 * output -
73 * side effects - initialises the various blockheaps
74 */
75void
76init_channels(void)
77{
dd9be678
WP
78 channel_heap = rb_bh_create(sizeof(struct Channel), CHANNEL_HEAP_SIZE, "channel_heap");
79 ban_heap = rb_bh_create(sizeof(struct Ban), BAN_HEAP_SIZE, "ban_heap");
80 topic_heap = rb_bh_create(TOPICLEN + 1 + USERHOST_REPLYLEN, TOPIC_HEAP_SIZE, "topic_heap");
81 member_heap = rb_bh_create(sizeof(struct membership), MEMBER_HEAP_SIZE, "member_heap");
212380e3 82
83 h_can_join = register_hook("can_join");
67b90240
JH
84 h_channel_join = register_hook("channel_join");
85 h_can_create_channel = register_hook("can_create_channel");
212380e3 86}
87
88/*
89 * allocate_channel - Allocates a channel
90 */
91struct Channel *
92allocate_channel(const char *chname)
93{
94 struct Channel *chptr;
6e9b4415 95 chptr = rb_bh_alloc(channel_heap);
62d28946 96 chptr->chname = rb_strdup(chname);
212380e3 97 return (chptr);
98}
99
100void
101free_channel(struct Channel *chptr)
102{
90a3c35b 103 rb_free(chptr->chname);
6e9b4415 104 rb_bh_free(channel_heap, chptr);
212380e3 105}
106
107struct Ban *
108allocate_ban(const char *banstr, const char *who)
109{
110 struct Ban *bptr;
6e9b4415 111 bptr = rb_bh_alloc(ban_heap);
62d28946
VY
112 bptr->banstr = rb_strdup(banstr);
113 bptr->who = rb_strdup(who);
212380e3 114
115 return (bptr);
116}
117
118void
119free_ban(struct Ban *bptr)
120{
90a3c35b
VY
121 rb_free(bptr->banstr);
122 rb_free(bptr->who);
6e9b4415 123 rb_bh_free(ban_heap, bptr);
212380e3 124}
125
126
127/* find_channel_membership()
128 *
129 * input - channel to find them in, client to find
130 * output - membership of client in channel, else NULL
131 * side effects -
132 */
133struct membership *
134find_channel_membership(struct Channel *chptr, struct Client *client_p)
135{
136 struct membership *msptr;
af81d5a0 137 rb_dlink_node *ptr;
212380e3 138
139 if(!IsClient(client_p))
140 return NULL;
141
142 /* Pick the most efficient list to use to be nice to things like
143 * CHANSERV which could be in a large number of channels
144 */
af81d5a0 145 if(rb_dlink_list_length(&chptr->members) < rb_dlink_list_length(&client_p->user->channel))
212380e3 146 {
8e69bb4e 147 RB_DLINK_FOREACH(ptr, chptr->members.head)
212380e3 148 {
149 msptr = ptr->data;
150
151 if(msptr->client_p == client_p)
152 return msptr;
153 }
154 }
155 else
156 {
8e69bb4e 157 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
212380e3 158 {
159 msptr = ptr->data;
160
161 if(msptr->chptr == chptr)
162 return msptr;
163 }
164 }
165
166 return NULL;
167}
168
169/* find_channel_status()
170 *
171 * input - membership to get status for, whether we can combine flags
172 * output - flags of user on channel
173 * side effects -
174 */
175const char *
176find_channel_status(struct membership *msptr, int combine)
177{
b8643345 178 static char buffer[5];
212380e3 179 char *p;
180
181 p = buffer;
182
b8643345
G
183 if(is_owner(msptr))
184 {
185 if(!combine)
186 return "!";
187 *p++ = '!';
188 }
189
212380e3 190 if(is_chanop(msptr))
191 {
192 if(!combine)
193 return "@";
194 *p++ = '@';
195 }
196
b8643345
G
197 if(is_halfop(msptr))
198 {
199 if(!combine)
200 return "%";
201 *p++ = '%';
202 }
203
212380e3 204 if(is_voiced(msptr))
205 *p++ = '+';
206
207 *p = '\0';
208 return buffer;
209}
210
40c6b59b
G
211/* is_halfop()
212 *
213 * input - membership to check for halfops
214 * output - 1 if the user is halfopped, 0 if the user is not or halfop
215 * is disabled.
216 * side effects -
217 *
218 */
219int
220is_halfop(struct membership *msptr)
221{
222 /* will do something other than return 0 when owner is implemented */
223 if(!ConfigChannel.use_halfop)
224 return 0;
225 else
226 return 0;
227}
228
229/* is_owner()
230 *
231 * input - membership to check for owner
232 * output - 1 if the user is an owner, 0 if the user is not or owner
233 * is disabled.
234 * side effects -
235 *
236 */
237int
238is_owner(struct membership *msptr)
239{
240 /* will do something other than return 0 when owner is implemented */
241 if(!ConfigChannel.use_owner)
242 return 0;
243 else
244 return 0;
245}
246
d1c7eccf
G
247/* is_any_op()
248 *
249 * input - membership to check for ops
250 * output - 1 if the user is op, halfop, or owner, 0 elsewise
251 * side effects -
252 */
d1c7eccf
G
253int
254is_any_op(struct membership *msptr)
255{
40c6b59b 256 if(is_chanop(msptr) || is_halfop(msptr) || is_owner(msptr))
d1c7eccf
G
257 return 1;
258 else
259 return 0;
260}
261
bbc69733
G
262/* is_chanop_voiced()
263 *
264 * input - memebership to check for status
265 * output - 1 if the user is op, halfop, owner, or voice, 0 elsewise
266 * side effects -
267 */
268int
269is_chanop_voiced(struct membership *msptr)
270{
40c6b59b 271 if(is_chanop(msptr) || is_voiced(msptr) || is_halfop(msptr) || is_owner(msptr))
bbc69733
G
272 return 1;
273 else
274 return 0;
275}
276
b3b2ed97
G
277/* can_kick_deop()
278 *
279 * input - two memeberships
280 * output - 1 if the first memebership can kick/deop the second, 0 elsewise
281 * side effects -
282 */
283int
284can_kick_deop(struct membership *source, struct membership *target)
285{
40c6b59b 286 if(is_chanop(source) && !is_owner(target))
b3b2ed97 287 return 1;
40c6b59b
G
288 else if(is_halfop(source) && !is_any_op(target))
289 return 1;
290 else if(is_owner(source))
291 return 1;
292
293 return 0;
b3b2ed97
G
294}
295
212380e3 296/* add_user_to_channel()
297 *
298 * input - channel to add client to, client to add, channel flags
299 * output -
300 * side effects - user is added to channel
301 */
302void
303add_user_to_channel(struct Channel *chptr, struct Client *client_p, int flags)
304{
305 struct membership *msptr;
306
307 s_assert(client_p->user != NULL);
308 if(client_p->user == NULL)
309 return;
310
6e9b4415 311 msptr = rb_bh_alloc(member_heap);
212380e3 312
313 msptr->chptr = chptr;
314 msptr->client_p = client_p;
315 msptr->flags = flags;
316
af81d5a0
WP
317 rb_dlinkAdd(msptr, &msptr->usernode, &client_p->user->channel);
318 rb_dlinkAdd(msptr, &msptr->channode, &chptr->members);
212380e3 319
320 if(MyClient(client_p))
af81d5a0 321 rb_dlinkAdd(msptr, &msptr->locchannode, &chptr->locmembers);
212380e3 322}
323
324/* remove_user_from_channel()
325 *
326 * input - membership pointer to remove from channel
327 * output -
328 * side effects - membership (thus user) is removed from channel
329 */
330void
331remove_user_from_channel(struct membership *msptr)
332{
333 struct Client *client_p;
334 struct Channel *chptr;
335 s_assert(msptr != NULL);
336 if(msptr == NULL)
337 return;
338
339 client_p = msptr->client_p;
340 chptr = msptr->chptr;
341
af81d5a0
WP
342 rb_dlinkDelete(&msptr->usernode, &client_p->user->channel);
343 rb_dlinkDelete(&msptr->channode, &chptr->members);
212380e3 344
345 if(client_p->servptr == &me)
af81d5a0 346 rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
212380e3 347
af81d5a0 348 if(!(chptr->mode.mode & MODE_PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
212380e3 349 destroy_channel(chptr);
350
6e9b4415 351 rb_bh_free(member_heap, msptr);
212380e3 352
353 return;
354}
355
356/* remove_user_from_channels()
357 *
358 * input - user to remove from all channels
359 * output -
360 * side effects - user is removed from all channels
361 */
362void
363remove_user_from_channels(struct Client *client_p)
364{
365 struct Channel *chptr;
366 struct membership *msptr;
af81d5a0 367 rb_dlink_node *ptr;
90a3c35b 368 rb_dlink_node *next_ptr;
212380e3 369
370 if(client_p == NULL)
371 return;
372
90a3c35b 373 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->user->channel.head)
212380e3 374 {
375 msptr = ptr->data;
376 chptr = msptr->chptr;
377
af81d5a0 378 rb_dlinkDelete(&msptr->channode, &chptr->members);
212380e3 379
380 if(client_p->servptr == &me)
af81d5a0 381 rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
212380e3 382
af81d5a0 383 if(!(chptr->mode.mode & MODE_PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
212380e3 384 destroy_channel(chptr);
385
6e9b4415 386 rb_bh_free(member_heap, msptr);
212380e3 387 }
388
389 client_p->user->channel.head = client_p->user->channel.tail = NULL;
390 client_p->user->channel.length = 0;
391}
392
393/* invalidate_bancache_user()
394 *
395 * input - user to invalidate ban cache for
396 * output -
397 * side effects - ban cache is invalidated for all memberships of that user
398 * to be used after a nick change
399 */
400void
401invalidate_bancache_user(struct Client *client_p)
402{
403 struct membership *msptr;
af81d5a0 404 rb_dlink_node *ptr;
212380e3 405
406 if(client_p == NULL)
407 return;
408
8e69bb4e 409 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
212380e3 410 {
411 msptr = ptr->data;
412 msptr->bants = 0;
413 msptr->flags &= ~CHFL_BANNED;
414 }
415}
416
417/* check_channel_name()
418 *
419 * input - channel name
420 * output - 1 if valid channel name, else 0
421 * side effects -
422 */
423int
424check_channel_name(const char *name)
425{
426 s_assert(name != NULL);
427 if(name == NULL)
428 return 0;
429
430 for (; *name; ++name)
431 {
432 if(!IsChanChar(*name))
433 return 0;
434 }
435
436 return 1;
437}
438
439/* free_channel_list()
440 *
af81d5a0 441 * input - rb_dlink list to free
212380e3 442 * output -
443 * side effects - list of b/e/I modes is cleared
444 */
445void
af81d5a0 446free_channel_list(rb_dlink_list * list)
212380e3 447{
af81d5a0 448 rb_dlink_node *ptr;
90a3c35b 449 rb_dlink_node *next_ptr;
212380e3 450 struct Ban *actualBan;
451
90a3c35b 452 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
212380e3 453 {
454 actualBan = ptr->data;
455 free_ban(actualBan);
456 }
457
458 list->head = list->tail = NULL;
459 list->length = 0;
460}
461
462/* destroy_channel()
463 *
464 * input - channel to destroy
465 * output -
466 * side effects - channel is obliterated
467 */
468void
469destroy_channel(struct Channel *chptr)
470{
90a3c35b 471 rb_dlink_node *ptr, *next_ptr;
212380e3 472
90a3c35b 473 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
212380e3 474 {
475 del_invite(chptr, ptr->data);
476 }
477
478 /* free all bans/exceptions/denies */
479 free_channel_list(&chptr->banlist);
480 free_channel_list(&chptr->exceptlist);
481 free_channel_list(&chptr->invexlist);
fea1ad52 482 free_channel_list(&chptr->quietlist);
212380e3 483
484 /* Free the topic */
485 free_topic(chptr);
486
af81d5a0 487 rb_dlinkDelete(&chptr->node, &global_channel_list);
212380e3 488 del_from_channel_hash(chptr->chname, chptr);
489 free_channel(chptr);
490}
491
492/* channel_pub_or_secret()
493 *
494 * input - channel
495 * output - "=" if public, "@" if secret, else "*"
496 * side effects -
497 */
498static const char *
499channel_pub_or_secret(struct Channel *chptr)
500{
501 if(PubChannel(chptr))
502 return ("=");
503 else if(SecretChannel(chptr))
504 return ("@");
505 return ("*");
506}
507
508/* channel_member_names()
509 *
510 * input - channel to list, client to list to, show endofnames
511 * output -
512 * side effects - client is given list of users on channel
513 */
514void
515channel_member_names(struct Channel *chptr, struct Client *client_p, int show_eon)
516{
517 struct membership *msptr;
518 struct Client *target_p;
af81d5a0 519 rb_dlink_node *ptr;
212380e3 520 char lbuf[BUFSIZE];
521 char *t;
522 int mlen;
523 int tlen;
524 int cur_len;
525 int is_member;
526 int stack = IsCapable(client_p, CLICAP_MULTI_PREFIX);
527
528 if(ShowChannel(client_p, chptr))
529 {
530 is_member = IsMember(client_p, chptr);
531
38e6acdd 532 cur_len = mlen = rb_sprintf(lbuf, form_str(RPL_NAMREPLY),
212380e3 533 me.name, client_p->name,
534 channel_pub_or_secret(chptr), chptr->chname);
535
536 t = lbuf + cur_len;
537
8e69bb4e 538 RB_DLINK_FOREACH(ptr, chptr->members.head)
212380e3 539 {
540 msptr = ptr->data;
541 target_p = msptr->client_p;
542
543 if(IsInvisible(target_p) && !is_member)
544 continue;
545
546 /* space, possible "@+" prefix */
547 if(cur_len + strlen(target_p->name) + 3 >= BUFSIZE - 3)
548 {
549 *(t - 1) = '\0';
550 sendto_one(client_p, "%s", lbuf);
551 cur_len = mlen;
552 t = lbuf + mlen;
553 }
554
38e6acdd 555 tlen = rb_sprintf(t, "%s%s ", find_channel_status(msptr, stack),
212380e3 556 target_p->name);
557
558 cur_len += tlen;
559 t += tlen;
560 }
561
562 /* The old behaviour here was to always output our buffer,
563 * even if there are no clients we can show. This happens
564 * when a client does "NAMES" with no parameters, and all
565 * the clients on a -sp channel are +i. I dont see a good
566 * reason for keeping that behaviour, as it just wastes
567 * bandwidth. --anfl
568 */
569 if(cur_len != mlen)
570 {
571 *(t - 1) = '\0';
572 sendto_one(client_p, "%s", lbuf);
573 }
574 }
575
576 if(show_eon)
577 sendto_one(client_p, form_str(RPL_ENDOFNAMES),
578 me.name, client_p->name, chptr->chname);
579}
580
581/* del_invite()
582 *
583 * input - channel to remove invite from, client to remove
584 * output -
585 * side effects - user is removed from invite list, if exists
586 */
587void
588del_invite(struct Channel *chptr, struct Client *who)
589{
af81d5a0
WP
590 rb_dlinkFindDestroy(who, &chptr->invites);
591 rb_dlinkFindDestroy(chptr, &who->user->invited);
212380e3 592}
593
594/* is_banned()
595 *
596 * input - channel to check bans for, user to check bans against
597 * optional prebuilt buffers
598 * output - 1 if banned, else 0
599 * side effects -
600 */
601int
602is_banned(struct Channel *chptr, struct Client *who, struct membership *msptr,
603 const char *s, const char *s2)
604{
605 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
606 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
607 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
608 char *s3 = NULL;
af81d5a0 609 rb_dlink_node *ptr;
212380e3 610 struct Ban *actualBan = NULL;
611 struct Ban *actualExcept = NULL;
612
613 if(!MyClient(who))
614 return 0;
615
616 /* if the buffers havent been built, do it here */
617 if(s == NULL)
618 {
38e6acdd
WP
619 rb_sprintf(src_host, "%s!%s@%s", who->name, who->username, who->host);
620 rb_sprintf(src_iphost, "%s!%s@%s", who->name, who->username, who->sockhost);
212380e3 621
622 s = src_host;
623 s2 = src_iphost;
624 }
625 if(who->localClient->mangledhost != NULL)
626 {
627 /* if host mangling mode enabled, also check their real host */
628 if(!strcmp(who->host, who->localClient->mangledhost))
629 {
38e6acdd 630 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->orighost);
212380e3 631 s3 = src_althost;
632 }
633 /* if host mangling mode not enabled and no other spoof,
634 * also check the mangled form of their host */
635 else if (!IsDynSpoof(who))
636 {
38e6acdd 637 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->localClient->mangledhost);
212380e3 638 s3 = src_althost;
639 }
640 }
641
8e69bb4e 642 RB_DLINK_FOREACH(ptr, chptr->banlist.head)
212380e3 643 {
644 actualBan = ptr->data;
645 if(match(actualBan->banstr, s) ||
646 match(actualBan->banstr, s2) ||
647 match_cidr(actualBan->banstr, s2) ||
648 match_extban(actualBan->banstr, who, chptr, CHFL_BAN) ||
649 (s3 != NULL && match(actualBan->banstr, s3)))
650 break;
651 else
652 actualBan = NULL;
653 }
654
655 if((actualBan != NULL) && ConfigChannel.use_except)
656 {
8e69bb4e 657 RB_DLINK_FOREACH(ptr, chptr->exceptlist.head)
212380e3 658 {
659 actualExcept = ptr->data;
660
661 /* theyre exempted.. */
662 if(match(actualExcept->banstr, s) ||
663 match(actualExcept->banstr, s2) ||
664 match_cidr(actualExcept->banstr, s2) ||
665 match_extban(actualExcept->banstr, who, chptr, CHFL_EXCEPTION) ||
666 (s3 != NULL && match(actualExcept->banstr, s3)))
667 {
668 /* cache the fact theyre not banned */
669 if(msptr != NULL)
670 {
671 msptr->bants = chptr->bants;
672 msptr->flags &= ~CHFL_BANNED;
673 }
674
675 return CHFL_EXCEPTION;
676 }
677 }
678 }
679
680 /* cache the banned/not banned status */
681 if(msptr != NULL)
682 {
683 msptr->bants = chptr->bants;
684
685 if(actualBan != NULL)
686 {
687 msptr->flags |= CHFL_BANNED;
688 return CHFL_BAN;
689 }
690 else
691 {
692 msptr->flags &= ~CHFL_BANNED;
693 return 0;
694 }
695 }
696
697 return ((actualBan ? CHFL_BAN : 0));
698}
699
700/* is_quieted()
701 *
702 * input - channel to check bans for, user to check bans against
703 * optional prebuilt buffers
704 * output - 1 if banned, else 0
705 * side effects -
706 */
707int
708is_quieted(struct Channel *chptr, struct Client *who, struct membership *msptr,
709 const char *s, const char *s2)
710{
711 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
712 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
713 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
714 char *s3 = NULL;
af81d5a0 715 rb_dlink_node *ptr;
212380e3 716 struct Ban *actualBan = NULL;
717 struct Ban *actualExcept = NULL;
718
719 if(!MyClient(who))
720 return 0;
721
722 /* if the buffers havent been built, do it here */
723 if(s == NULL)
724 {
38e6acdd
WP
725 rb_sprintf(src_host, "%s!%s@%s", who->name, who->username, who->host);
726 rb_sprintf(src_iphost, "%s!%s@%s", who->name, who->username, who->sockhost);
212380e3 727
728 s = src_host;
729 s2 = src_iphost;
730 }
731 if(who->localClient->mangledhost != NULL)
732 {
733 /* if host mangling mode enabled, also check their real host */
734 if(!strcmp(who->host, who->localClient->mangledhost))
735 {
38e6acdd 736 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->orighost);
212380e3 737 s3 = src_althost;
738 }
739 /* if host mangling mode not enabled and no other spoof,
740 * also check the mangled form of their host */
741 else if (!IsDynSpoof(who))
742 {
38e6acdd 743 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->localClient->mangledhost);
212380e3 744 s3 = src_althost;
745 }
746 }
747
8e69bb4e 748 RB_DLINK_FOREACH(ptr, chptr->quietlist.head)
212380e3 749 {
750 actualBan = ptr->data;
751 if(match(actualBan->banstr, s) ||
752 match(actualBan->banstr, s2) ||
753 match_cidr(actualBan->banstr, s2) ||
754 match_extban(actualBan->banstr, who, chptr, CHFL_QUIET) ||
755 (s3 != NULL && match(actualBan->banstr, s3)))
756 break;
757 else
758 actualBan = NULL;
759 }
760
761 if((actualBan != NULL) && ConfigChannel.use_except)
762 {
8e69bb4e 763 RB_DLINK_FOREACH(ptr, chptr->exceptlist.head)
212380e3 764 {
765 actualExcept = ptr->data;
766
767 /* theyre exempted.. */
768 if(match(actualExcept->banstr, s) ||
769 match(actualExcept->banstr, s2) ||
770 match_cidr(actualExcept->banstr, s2) ||
771 match_extban(actualExcept->banstr, who, chptr, CHFL_EXCEPTION) ||
772 (s3 != NULL && match(actualExcept->banstr, s3)))
773 {
774 /* cache the fact theyre not banned */
775 if(msptr != NULL)
776 {
777 msptr->bants = chptr->bants;
778 msptr->flags &= ~CHFL_BANNED;
779 }
780
781 return CHFL_EXCEPTION;
782 }
783 }
784 }
785
786 /* cache the banned/not banned status */
787 if(msptr != NULL)
788 {
789 msptr->bants = chptr->bants;
790
791 if(actualBan != NULL)
792 {
793 msptr->flags |= CHFL_BANNED;
794 return CHFL_BAN;
795 }
796 else
797 {
798 msptr->flags &= ~CHFL_BANNED;
799 return 0;
800 }
801 }
802
803 return ((actualBan ? CHFL_BAN : 0));
804}
805
806/* can_join()
807 *
808 * input - client to check, channel to check for, key
809 * output - reason for not being able to join, else 0
810 * side effects -
811 */
812int
813can_join(struct Client *source_p, struct Channel *chptr, char *key)
814{
af81d5a0
WP
815 rb_dlink_node *invite = NULL;
816 rb_dlink_node *ptr;
212380e3 817 struct Ban *invex = NULL;
818 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
819 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
820 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
821 int use_althost = 0;
1ebf4db4 822 int i = 0;
212380e3 823 hook_data_channel moduledata;
824
825 s_assert(source_p->localClient != NULL);
826
13a467bb
JH
827 if(IsOverride(source_p))
828 return 0;
829
38e6acdd
WP
830 rb_sprintf(src_host, "%s!%s@%s", source_p->name, source_p->username, source_p->host);
831 rb_sprintf(src_iphost, "%s!%s@%s", source_p->name, source_p->username, source_p->sockhost);
212380e3 832 if(source_p->localClient->mangledhost != NULL)
833 {
834 /* if host mangling mode enabled, also check their real host */
835 if(!strcmp(source_p->host, source_p->localClient->mangledhost))
836 {
38e6acdd 837 rb_sprintf(src_althost, "%s!%s@%s", source_p->name, source_p->username, source_p->orighost);
212380e3 838 use_althost = 1;
839 }
840 /* if host mangling mode not enabled and no other spoof,
841 * also check the mangled form of their host */
842 else if (!IsDynSpoof(source_p))
843 {
38e6acdd 844 rb_sprintf(src_althost, "%s!%s@%s", source_p->name, source_p->username, source_p->localClient->mangledhost);
212380e3 845 use_althost = 1;
846 }
847 }
848
849 if((is_banned(chptr, source_p, NULL, src_host, src_iphost)) == CHFL_BAN)
850 return (ERR_BANNEDFROMCHAN);
851
852 if(chptr->mode.mode & MODE_INVITEONLY)
853 {
8e69bb4e 854 RB_DLINK_FOREACH(invite, source_p->user->invited.head)
212380e3 855 {
1ebf4db4 856 if(invite->data == chptr)
212380e3 857 break;
858 }
1ebf4db4 859 if(invite == NULL)
212380e3 860 {
861 if(!ConfigChannel.use_invex)
862 return (ERR_INVITEONLYCHAN);
8e69bb4e 863 RB_DLINK_FOREACH(ptr, chptr->invexlist.head)
212380e3 864 {
865 invex = ptr->data;
866 if(match(invex->banstr, src_host)
867 || match(invex->banstr, src_iphost)
868 || match_cidr(invex->banstr, src_iphost)
869 || match_extban(invex->banstr, source_p, chptr, CHFL_INVEX)
870 || (use_althost && match(invex->banstr, src_althost)))
871 break;
872 }
873 if(ptr == NULL)
874 return (ERR_INVITEONLYCHAN);
875 }
876 }
877
878 if(*chptr->mode.key && (EmptyString(key) || irccmp(chptr->mode.key, key)))
879 return (ERR_BADCHANNELKEY);
880
881 if(chptr->mode.limit &&
af81d5a0 882 rb_dlink_list_length(&chptr->members) >= (unsigned long) chptr->mode.limit)
1ebf4db4 883 i = ERR_CHANNELISFULL;
212380e3 884 if(chptr->mode.mode & MODE_REGONLY && EmptyString(source_p->user->suser))
1ebf4db4 885 i = ERR_NEEDREGGEDNICK;
212380e3 886 /* join throttling stuff --nenolod */
1ebf4db4 887 else if(chptr->mode.join_num > 0 && chptr->mode.join_time > 0)
212380e3 888 {
9f6bbe3c 889 if ((rb_current_time() - chptr->join_delta <=
212380e3 890 chptr->mode.join_time) && (chptr->join_count >=
891 chptr->mode.join_num))
1ebf4db4 892 i = ERR_THROTTLE;
893 }
894
895 /* allow /invite to override +l/+r/+j also -- jilles */
896 if (i != 0 && invite == NULL)
897 {
8e69bb4e 898 RB_DLINK_FOREACH(invite, source_p->user->invited.head)
1ebf4db4 899 {
900 if(invite->data == chptr)
901 break;
902 }
903 if (invite == NULL)
904 return i;
212380e3 905 }
906
907 moduledata.client = source_p;
908 moduledata.chptr = chptr;
909 moduledata.approved = 0;
910
911 call_hook(h_can_join, &moduledata);
912
913 return moduledata.approved;
914}
915
916/* can_send()
917 *
918 * input - user to check in channel, membership pointer
919 * output - whether can explicitly send or not, else CAN_SEND_NONOP
920 * side effects -
921 */
922int
923can_send(struct Channel *chptr, struct Client *source_p, struct membership *msptr)
924{
925 if(IsServer(source_p) || IsService(source_p))
926 return CAN_SEND_OPV;
927
928 if(MyClient(source_p) && hash_find_resv(chptr->chname) &&
929 !IsOper(source_p) && !IsExemptResv(source_p))
930 return CAN_SEND_NO;
931
932 if(msptr == NULL)
933 {
934 msptr = find_channel_membership(chptr, source_p);
935
936 if(msptr == NULL)
937 {
938 /* if its +m or +n and theyre not in the channel,
939 * they cant send. we dont check bans here because
940 * theres no possibility of caching them --fl
941 */
942 if(chptr->mode.mode & MODE_NOPRIVMSGS || chptr->mode.mode & MODE_MODERATED)
943 return CAN_SEND_NO;
944 else
945 return CAN_SEND_NONOP;
946 }
947 }
948
949 if(is_chanop_voiced(msptr))
950 return CAN_SEND_OPV;
951
13a467bb
JH
952 if(IsOverride(source_p))
953 return CAN_SEND_NONOP;
954
212380e3 955 if(chptr->mode.mode & MODE_MODERATED)
956 return CAN_SEND_NO;
957
958 if(MyClient(source_p))
959 {
960 /* cached can_send */
961 if(msptr->bants == chptr->bants)
962 {
963 if(can_send_banned(msptr))
964 return CAN_SEND_NO;
965 }
966 else if(is_banned(chptr, source_p, msptr, NULL, NULL) == CHFL_BAN
967 || is_quieted(chptr, source_p, msptr, NULL, NULL) == CHFL_BAN)
968 return CAN_SEND_NO;
969 }
970
971 return CAN_SEND_NONOP;
972}
973
974/* find_bannickchange_channel()
975 * Input: client to check
976 * Output: channel preventing nick change
977 */
978struct Channel *
979find_bannickchange_channel(struct Client *client_p)
980{
981 struct Channel *chptr;
982 struct membership *msptr;
af81d5a0 983 rb_dlink_node *ptr;
212380e3 984 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
985 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
986
13a467bb 987 if (!MyClient(client_p) || IsOverride(client_p))
212380e3 988 return NULL;
989
38e6acdd
WP
990 rb_sprintf(src_host, "%s!%s@%s", client_p->name, client_p->username, client_p->host);
991 rb_sprintf(src_iphost, "%s!%s@%s", client_p->name, client_p->username, client_p->sockhost);
212380e3 992
8e69bb4e 993 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
212380e3 994 {
995 msptr = ptr->data;
996 chptr = msptr->chptr;
997 if (is_chanop_voiced(msptr))
998 continue;
999 /* cached can_send */
1000 if (msptr->bants == chptr->bants)
1001 {
1002 if (can_send_banned(msptr))
1003 return chptr;
1004 }
1005 else if (is_banned(chptr, client_p, msptr, src_host, src_iphost) == CHFL_BAN
1006 || is_quieted(chptr, client_p, msptr, src_host, src_iphost) == CHFL_BAN)
1007 return chptr;
1008 }
1009 return NULL;
1010}
1011
afd4834b
G
1012/* find_nonickchange_channel()
1013 * Input: client to check
1014 * Output: channel preventing nick change
1015 */
1016struct Channel *
1017find_nonickchange_channel(struct Client *client_p)
1018{
1019 struct Channel *chptr;
1020 struct membership *msptr;
1021 rb_dlink_node *ptr;
1022
1023 if (!MyClient(client_p))
1024 return NULL;
1025
1026 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
1027 {
1028 msptr = ptr->data;
1029 chptr = msptr->chptr;
d1c7eccf 1030 if (is_any_op(msptr))
afd4834b
G
1031 continue;
1032 if (chptr->mode.mode & MODE_NONICK)
1033 return chptr;
1034 }
1035 return NULL;
1036}
1037
212380e3 1038/* void check_spambot_warning(struct Client *source_p)
1039 * Input: Client to check, channel name or NULL if this is a part.
1040 * Output: none
1041 * Side-effects: Updates the client's oper_warn_count_down, warns the
1042 * IRC operators if necessary, and updates join_leave_countdown as
1043 * needed.
1044 */
1045void
1046check_spambot_warning(struct Client *source_p, const char *name)
1047{
1048 int t_delta;
1049 int decrement_count;
1050 if((GlobalSetOptions.spam_num &&
1051 (source_p->localClient->join_leave_count >= GlobalSetOptions.spam_num)))
1052 {
1053 if(source_p->localClient->oper_warn_count_down > 0)
1054 source_p->localClient->oper_warn_count_down--;
1055 else
1056 source_p->localClient->oper_warn_count_down = 0;
05d8a68c
JT
1057 if(source_p->localClient->oper_warn_count_down == 0 &&
1058 name != NULL)
212380e3 1059 {
1060 /* Its already known as a possible spambot */
05d8a68c
JT
1061 sendto_realops_snomask(SNO_BOTS, L_NETWIDE,
1062 "User %s (%s@%s) trying to join %s is a possible spambot",
1063 source_p->name,
1064 source_p->username, source_p->orighost, name);
212380e3 1065 source_p->localClient->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
1066 }
1067 }
1068 else
1069 {
1070 if((t_delta =
9f6bbe3c 1071 (rb_current_time() - source_p->localClient->last_leave_time)) >
212380e3 1072 JOIN_LEAVE_COUNT_EXPIRE_TIME)
1073 {
1074 decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
b6698246
JT
1075 if(name != NULL)
1076 ;
1077 else if(decrement_count > source_p->localClient->join_leave_count)
212380e3 1078 source_p->localClient->join_leave_count = 0;
1079 else
1080 source_p->localClient->join_leave_count -= decrement_count;
1081 }
1082 else
1083 {
9f6bbe3c 1084 if((rb_current_time() -
212380e3 1085 (source_p->localClient->last_join_time)) < GlobalSetOptions.spam_time)
1086 {
1087 /* oh, its a possible spambot */
1088 source_p->localClient->join_leave_count++;
1089 }
1090 }
1091 if(name != NULL)
9f6bbe3c 1092 source_p->localClient->last_join_time = rb_current_time();
212380e3 1093 else
9f6bbe3c 1094 source_p->localClient->last_leave_time = rb_current_time();
212380e3 1095 }
1096}
1097
1098/* check_splitmode()
1099 *
1100 * input -
1101 * output -
1102 * side effects - compares usercount and servercount against their split
1103 * values and adjusts splitmode accordingly
1104 */
1105void
1106check_splitmode(void *unused)
1107{
1108 if(splitchecking && (ConfigChannel.no_join_on_split || ConfigChannel.no_create_on_split))
1109 {
1110 /* not split, we're being asked to check now because someone
1111 * has left
1112 */
1113 if(!splitmode)
1114 {
1115 if(eob_count < split_servers || Count.total < split_users)
1116 {
1117 splitmode = 1;
1118 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1119 "Network split, activating splitmode");
dd9be678 1120 check_splitmode_ev = rb_event_addish("check_splitmode", check_splitmode, NULL, 2);
212380e3 1121 }
1122 }
1123 /* in splitmode, check whether its finished */
1124 else if(eob_count >= split_servers && Count.total >= split_users)
1125 {
1126 splitmode = 0;
1127
1128 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1129 "Network rejoined, deactivating splitmode");
1130
dd9be678 1131 rb_event_delete(check_splitmode_ev);
0ae330b4 1132 check_splitmode_ev = NULL;
212380e3 1133 }
1134 }
1135}
1136
1137
1138/* allocate_topic()
1139 *
1140 * input - channel to allocate topic for
1141 * output - 1 on success, else 0
1142 * side effects - channel gets a topic allocated
1143 */
1144static void
1145allocate_topic(struct Channel *chptr)
1146{
1147 void *ptr;
1148
1149 if(chptr == NULL)
1150 return;
1151
6e9b4415 1152 ptr = rb_bh_alloc(topic_heap);
212380e3 1153
1154 /* Basically we allocate one large block for the topic and
1155 * the topic info. We then split it up into two and shove it
1156 * in the chptr
1157 */
1158 chptr->topic = ptr;
1159 chptr->topic_info = (char *) ptr + TOPICLEN + 1;
1160 *chptr->topic = '\0';
1161 *chptr->topic_info = '\0';
1162}
1163
1164/* free_topic()
1165 *
1166 * input - channel which has topic to free
1167 * output -
1168 * side effects - channels topic is free'd
1169 */
1170static void
1171free_topic(struct Channel *chptr)
1172{
1173 void *ptr;
1174
1175 if(chptr == NULL || chptr->topic == NULL)
1176 return;
1177
1178 /* This is safe for now - If you change allocate_topic you
1179 * MUST change this as well
1180 */
1181 ptr = chptr->topic;
6e9b4415 1182 rb_bh_free(topic_heap, ptr);
212380e3 1183 chptr->topic = NULL;
1184 chptr->topic_info = NULL;
1185}
1186
1187/* set_channel_topic()
1188 *
1189 * input - channel, topic to set, topic info and topic ts
1190 * output -
1191 * side effects - channels topic, topic info and TS are set.
1192 */
1193void
1194set_channel_topic(struct Channel *chptr, const char *topic, const char *topic_info, time_t topicts)
1195{
1196 if(strlen(topic) > 0)
1197 {
1198 if(chptr->topic == NULL)
1199 allocate_topic(chptr);
907468c4
VY
1200 rb_strlcpy(chptr->topic, topic, TOPICLEN + 1);
1201 rb_strlcpy(chptr->topic_info, topic_info, USERHOST_REPLYLEN);
212380e3 1202 chptr->topic_time = topicts;
1203 }
1204 else
1205 {
1206 if(chptr->topic != NULL)
1207 free_topic(chptr);
1208 chptr->topic_time = 0;
1209 }
1210}
1211
c279d43b
G
1212/* has_common_channel()
1213 *
1214 * input - pointer to client
1215 * - pointer to another client
1216 * output - 1 if the two have a channel in common, 0 elsewise
1217 * side effects - none
1218 */
1219int
1220has_common_channel(struct Client *client1, struct Client *client2)
1221{
1222 rb_dlink_node *ptr;
1223
1224 RB_DLINK_FOREACH(ptr, client1->user->channel.head)
1225 {
1226 if(IsMember(client2, ((struct membership *)ptr->data)->chptr))
1227 return 1;
1228 }
99c78094 1229 return 0;
c279d43b
G
1230}
1231
212380e3 1232/* channel_modes()
1233 *
1234 * inputs - pointer to channel
1235 * - pointer to client
f1e35c19 1236 * output - string with simple modes
1237 * side effects - result from previous calls overwritten
212380e3 1238 *
1239 * Stolen from ShadowIRCd 4 --nenolod
1240 */
1241const char *
1242channel_modes(struct Channel *chptr, struct Client *client_p)
1243{
1244 int i;
1245 char buf1[BUFSIZE];
1246 char buf2[BUFSIZE];
1247 static char final[BUFSIZE];
1248 char *mbuf = buf1;
1249 char *pbuf = buf2;
1250
1251 *mbuf++ = '+';
1252 *pbuf = '\0';
1253
75818939
VY
1254 for (i = 0; i < 256; i++)
1255 if(chptr->mode.mode & chmode_flags[i])
1256 *mbuf++ = i;
212380e3 1257
1258 if(chptr->mode.limit)
1259 {
1260 *mbuf++ = 'l';
1261
f1e35c19 1262 if(!IsClient(client_p) || IsMember(client_p, chptr))
38e6acdd 1263 pbuf += rb_sprintf(pbuf, " %d", chptr->mode.limit);
212380e3 1264 }
1265
1266 if(*chptr->mode.key)
1267 {
1268 *mbuf++ = 'k';
1269
f1e35c19 1270 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
38e6acdd 1271 pbuf += rb_sprintf(pbuf, " %s", chptr->mode.key);
212380e3 1272 }
1273
1274 if(chptr->mode.join_num)
1275 {
1276 *mbuf++ = 'j';
1277
f1e35c19 1278 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
38e6acdd 1279 pbuf += rb_sprintf(pbuf, " %d:%d", chptr->mode.join_num,
212380e3 1280 chptr->mode.join_time);
1281 }
1282
f1e35c19 1283 if(*chptr->mode.forward && (ConfigChannel.use_forward || !IsClient(client_p)))
212380e3 1284 {
1285 *mbuf++ = 'f';
1286
f1e35c19 1287 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
38e6acdd 1288 pbuf += rb_sprintf(pbuf, " %s", chptr->mode.forward);
212380e3 1289 }
1290
1291 *mbuf = '\0';
1292
907468c4 1293 rb_strlcpy(final, buf1, sizeof final);
a64c5173 1294 rb_strlcat(final, buf2, sizeof final);
212380e3 1295 return final;
1296}
1297
1298/* Now lets do some stuff to keep track of what combinations of
1299 * servers exist...
1300 * Note that the number of combinations doubles each time you add
1301 * something to this list. Each one is only quick if no servers use that
1302 * combination, but if the numbers get too high here MODE will get too
1303 * slow. I suggest if you get more than 7 here, you consider getting rid
1304 * of some and merging or something. If it wasn't for irc+cs we would
1305 * probably not even need to bother about most of these, but unfortunately
1306 * we do. -A1kmm
1307 */
1308
1309/* void init_chcap_usage_counts(void)
1310 *
1311 * Inputs - none
1312 * Output - none
1313 * Side-effects - Initialises the usage counts to zero. Fills in the
1314 * chcap_yes and chcap_no combination tables.
1315 */
1316void
1317init_chcap_usage_counts(void)
1318{
1319 unsigned long m, c, y, n;
1320
1321 memset(chcap_combos, 0, sizeof(chcap_combos));
1322
1323 /* For every possible combination */
1324 for (m = 0; m < NCHCAP_COMBOS; m++)
1325 {
1326 /* Check each capab */
1327 for (c = y = n = 0; c < NCHCAPS; c++)
1328 {
1329 if((m & (1 << c)) == 0)
1330 n |= channel_capabs[c];
1331 else
1332 y |= channel_capabs[c];
1333 }
1334 chcap_combos[m].cap_yes = y;
1335 chcap_combos[m].cap_no = n;
1336 }
1337}
1338
1339/* void set_chcap_usage_counts(struct Client *serv_p)
1340 * Input: serv_p; The client whose capabs to register.
1341 * Output: none
1342 * Side-effects: Increments the usage counts for the correct capab
1343 * combination.
1344 */
1345void
1346set_chcap_usage_counts(struct Client *serv_p)
1347{
1348 int n;
1349
1350 for (n = 0; n < NCHCAP_COMBOS; n++)
1351 {
1352 if(IsCapable(serv_p, chcap_combos[n].cap_yes) &&
1353 NotCapable(serv_p, chcap_combos[n].cap_no))
1354 {
1355 chcap_combos[n].count++;
1356 return;
1357 }
1358 }
1359
1360 /* This should be impossible -A1kmm. */
1361 s_assert(0);
1362}
1363
1364/* void set_chcap_usage_counts(struct Client *serv_p)
1365 *
1366 * Inputs - serv_p; The client whose capabs to register.
1367 * Output - none
1368 * Side-effects - Decrements the usage counts for the correct capab
1369 * combination.
1370 */
1371void
1372unset_chcap_usage_counts(struct Client *serv_p)
1373{
1374 int n;
1375
1376 for (n = 0; n < NCHCAP_COMBOS; n++)
1377 {
1378 if(IsCapable(serv_p, chcap_combos[n].cap_yes) &&
1379 NotCapable(serv_p, chcap_combos[n].cap_no))
1380 {
1381 /* Hopefully capabs can't change dynamically or anything... */
1382 s_assert(chcap_combos[n].count > 0);
1383
1384 if(chcap_combos[n].count > 0)
1385 chcap_combos[n].count--;
1386 return;
1387 }
1388 }
1389
1390 /* This should be impossible -A1kmm. */
1391 s_assert(0);
1392}
1393
1394/* void send_cap_mode_changes(struct Client *client_p,
1395 * struct Client *source_p,
1396 * struct Channel *chptr, int cap, int nocap)
1397 * Input: The client sending(client_p), the source client(source_p),
1398 * the channel to send mode changes for(chptr)
1399 * Output: None.
1400 * Side-effects: Sends the appropriate mode changes to capable servers.
1401 *
1402 * Reverted back to my original design, except that we now keep a count
1403 * of the number of servers which each combination as an optimisation, so
1404 * the capabs combinations which are not needed are not worked out. -A1kmm
1405 */
1406void
1407send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
1408 struct Channel *chptr, struct ChModeChange mode_changes[], int mode_count)
1409{
1410 static char modebuf[BUFSIZE];
1411 static char parabuf[BUFSIZE];
1412 int i, mbl, pbl, nc, mc, preflen, len;
1413 char *pbuf;
1414 const char *arg;
1415 int dir;
1416 int j;
1417 int cap;
1418 int nocap;
1419 int arglen;
1420
1421 /* Now send to servers... */
1422 for (j = 0; j < NCHCAP_COMBOS; j++)
1423 {
1424 if(chcap_combos[j].count == 0)
1425 continue;
1426
1427 mc = 0;
1428 nc = 0;
1429 pbl = 0;
1430 parabuf[0] = 0;
1431 pbuf = parabuf;
1432 dir = MODE_QUERY;
1433
1434 cap = chcap_combos[j].cap_yes;
1435 nocap = chcap_combos[j].cap_no;
1436
9f9b4d7b
WP
1437 mbl = preflen = rb_sprintf(modebuf, ":%s TMODE %ld %s ",
1438 use_id(source_p), (long) chptr->channelts,
1439 chptr->chname);
212380e3 1440
1441 /* loop the list of - modes we have */
1442 for (i = 0; i < mode_count; i++)
1443 {
1444 /* if they dont support the cap we need, or they do support a cap they
1445 * cant have, then dont add it to the modebuf.. that way they wont see
1446 * the mode
1447 */
1448 if((mode_changes[i].letter == 0) ||
1449 ((cap & mode_changes[i].caps) != mode_changes[i].caps)
1450 || ((nocap & mode_changes[i].nocaps) != mode_changes[i].nocaps))
1451 continue;
1452
7592f950
JT
1453 if(!EmptyString(mode_changes[i].id))
1454 arg = mode_changes[i].id;
1455 else
1456 arg = mode_changes[i].arg;
212380e3 1457
1458 if(arg)
1459 {
1460 arglen = strlen(arg);
1461
1462 /* dont even think about it! --fl */
1463 if(arglen > MODEBUFLEN - 5)
1464 continue;
1465 }
1466
1467 /* if we're creeping past the buf size, we need to send it and make
1468 * another line for the other modes
1469 * XXX - this could give away server topology with uids being
1470 * different lengths, but not much we can do, except possibly break
1471 * them as if they were the longest of the nick or uid at all times,
1472 * which even then won't work as we don't always know the uid -A1kmm.
1473 */
1474 if(arg && ((mc == MAXMODEPARAMSSERV) ||
1475 ((mbl + pbl + arglen + 4) > (BUFSIZE - 3))))
1476 {
1477 if(nc != 0)
1478 sendto_server(client_p, chptr, cap, nocap,
1479 "%s %s", modebuf, parabuf);
1480 nc = 0;
1481 mc = 0;
1482
1483 mbl = preflen;
1484 pbl = 0;
1485 pbuf = parabuf;
1486 parabuf[0] = 0;
1487 dir = MODE_QUERY;
1488 }
1489
1490 if(dir != mode_changes[i].dir)
1491 {
1492 modebuf[mbl++] = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
1493 dir = mode_changes[i].dir;
1494 }
1495
1496 modebuf[mbl++] = mode_changes[i].letter;
1497 modebuf[mbl] = 0;
1498 nc++;
1499
1500 if(arg != NULL)
1501 {
38e6acdd 1502 len = rb_sprintf(pbuf, "%s ", arg);
212380e3 1503 pbuf += len;
1504 pbl += len;
1505 mc++;
1506 }
1507 }
1508
1509 if(pbl && parabuf[pbl - 1] == ' ')
1510 parabuf[pbl - 1] = 0;
1511
1512 if(nc != 0)
1513 sendto_server(client_p, chptr, cap, nocap, "%s %s", modebuf, parabuf);
1514 }
1515}
080bb5cf
JH
1516
1517/* Check what we will forward to, without sending any notices to the user
1518 * -- jilles
1519 */
1520struct Channel *
1521check_forward(struct Client *source_p, struct Channel *chptr,
1522 char *key)
1523{
1524 int depth = 0, i;
1525
1526 /* User is +Q */
1527 if (IsNoForward(source_p))
1528 return NULL;
1529
1530 while (depth < 16)
1531 {
1532 chptr = find_channel(chptr->mode.forward);
1533 /* Can only forward to existing channels */
1534 if (chptr == NULL)
1535 return NULL;
1536 /* Already on there, show original error message */
1537 if (IsMember(source_p, chptr))
1538 return NULL;
1539 /* Juped. Sending a warning notice would be unfair */
1540 if (hash_find_resv(chptr->chname))
1541 return NULL;
1542 /* Don't forward to +Q channel */
1543 if (chptr->mode.mode & MODE_DISFORWARD)
1544 return NULL;
1545 i = can_join(source_p, chptr, key);
1546 if (i == 0)
1547 return chptr;
1548 if (i != ERR_INVITEONLYCHAN && i != ERR_NEEDREGGEDNICK && i != ERR_THROTTLE && i != ERR_CHANNELISFULL)
1549 return NULL;
1550 depth++;
1551 }
1552
1553 return NULL;
1554}
67b90240 1555
9230426e
JH
1556/*
1557 * do_join_0
1558 *
1559 * inputs - pointer to client doing join 0
1560 * output - NONE
1561 * side effects - Use has decided to join 0. This is legacy
1562 * from the days when channels were numbers not names. *sigh*
9230426e
JH
1563 */
1564void
1565do_join_0(struct Client *client_p, struct Client *source_p)
1566{
1567 struct membership *msptr;
1568 struct Channel *chptr = NULL;
1569 rb_dlink_node *ptr;
1570
1571 /* Finish the flood grace period... */
1572 if(MyClient(source_p) && !IsFloodDone(source_p))
1573 flood_endgrace(source_p);
1574
1575 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s JOIN 0", use_id(source_p));
1576
aa35afbb
JH
1577 while((ptr = source_p->user->channel.head))
1578 {
9230426e
JH
1579 if(source_p->user->channel.head && MyConnect(source_p) &&
1580 !IsOper(source_p) && !IsExemptSpambot(source_p))
1581 check_spambot_warning(source_p, NULL);
1582
9230426e
JH
1583 msptr = ptr->data;
1584 chptr = msptr->chptr;
1585 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
1586 source_p->name,
1587 source_p->username, source_p->host, chptr->chname);
1588 remove_user_from_channel(msptr);
1589 }
1590}
1591
1592int
1593check_channel_name_loc(struct Client *source_p, const char *name)
1594{
aa35afbb
JH
1595 const char *p;
1596
9230426e
JH
1597 s_assert(name != NULL);
1598 if(EmptyString(name))
1599 return 0;
1600
1601 if(ConfigFileEntry.disable_fake_channels && !IsOper(source_p))
1602 {
aa35afbb 1603 for(p = name; *p; ++p)
9230426e 1604 {
aa35afbb 1605 if(!IsChanChar(*p) || IsFakeChanChar(*p))
9230426e
JH
1606 return 0;
1607 }
1608 }
1609 else
1610 {
aa35afbb 1611 for(p = name; *p; ++p)
9230426e 1612 {
aa35afbb 1613 if(!IsChanChar(*p))
9230426e
JH
1614 return 0;
1615 }
1616 }
1617
aa35afbb
JH
1618 if(ConfigChannel.only_ascii_channels)
1619 {
1620 for(p = name; *p; ++p)
1621 if(*p < 33 || *p > 126)
1622 return 0;
1623 }
1624
1625
9230426e
JH
1626 return 1;
1627}
1628
824455ab 1629void user_join(struct Client * client_p, struct Client * source_p, const char * channels, const char * keys)
67b90240
JH
1630{
1631 static char jbuf[BUFSIZE];
1632 struct Channel *chptr = NULL;
1633 struct ConfItem *aconf;
1634 char *name;
1635 char *key = NULL;
1636 const char *modes;
1637 int i, flags = 0;
1638 char *p = NULL, *p2 = NULL;
1639 char *chanlist;
1640 char *mykey;
67b90240
JH
1641
1642 jbuf[0] = '\0';
1643
1644 if(channels == NULL)
1645 return;
1646
1647 /* rebuild the list of channels theyre supposed to be joining.
1648 * this code has a side effect of losing keys, but..
1649 */
1650 chanlist = LOCAL_COPY(channels);
1651 for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
1652 {
1653 /* check the length and name of channel is ok */
1654 if(!check_channel_name_loc(source_p, name) || (strlen(name) > LOC_CHANNELLEN))
1655 {
1656 sendto_one_numeric(source_p, ERR_BADCHANNAME,
1657 form_str(ERR_BADCHANNAME), (unsigned char *) name);
1658 continue;
1659 }
1660
1661 /* join 0 parts all channels */
1662 if(*name == '0' && (name[1] == ',' || name[1] == '\0') && name == chanlist)
1663 {
1664 (void) strcpy(jbuf, "0");
1665 continue;
1666 }
1667
1668 /* check it begins with # or &, and local chans are disabled */
1669 else if(!IsChannelName(name))
1670 {
1671 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
1672 form_str(ERR_NOSUCHCHANNEL), name);
1673 continue;
1674 }
1675
1676 /* see if its resv'd */
1677 if(!IsExemptResv(source_p) && (aconf = hash_find_resv(name)))
1678 {
1679 sendto_one_numeric(source_p, ERR_BADCHANNAME,
1680 form_str(ERR_BADCHANNAME), name);
1681
1682 /* dont warn for opers */
1683 if(!IsExemptJupe(source_p) && !IsOper(source_p))
1684 sendto_realops_snomask(SNO_SPY, L_NETWIDE,
1685 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
1686 source_p->name, source_p->username,
1687 source_p->orighost, name, aconf->passwd);
1688 /* dont update tracking for jupe exempt users, these
1689 * are likely to be spamtrap leaves
1690 */
1691 else if(IsExemptJupe(source_p))
1692 aconf->port--;
1693
1694 continue;
1695 }
1696
1697 if(splitmode && !IsOper(source_p) && (*name != '&') &&
1698 ConfigChannel.no_join_on_split)
1699 {
1700 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
1701 me.name, source_p->name, name);
1702 continue;
1703 }
1704
1705 if(*jbuf)
1706 (void) strcat(jbuf, ",");
1707 (void) rb_strlcat(jbuf, name, sizeof(jbuf));
1708 }
1709
1710 if(keys != NULL)
1711 {
1712 mykey = LOCAL_COPY(keys);
1713 key = rb_strtok_r(mykey, ",", &p2);
1714 }
1715
1716 for(name = rb_strtok_r(jbuf, ",", &p); name;
1717 key = (key) ? rb_strtok_r(NULL, ",", &p2) : NULL, name = rb_strtok_r(NULL, ",", &p))
1718 {
1719 hook_data_channel_activity hook_info;
1720
1721 /* JOIN 0 simply parts all channels the user is in */
1722 if(*name == '0' && !atoi(name))
1723 {
1724 if(source_p->user->channel.head == NULL)
1725 continue;
1726
1727 do_join_0(&me, source_p);
1728 continue;
1729 }
1730
1731 /* look for the channel */
1732 if((chptr = find_channel(name)) != NULL)
1733 {
1734 if(IsMember(source_p, chptr))
1735 continue;
1736
1737 flags = 0;
1738 }
1739 else
1740 {
1741 hook_data_client_approval moduledata;
1742
1743 moduledata.client = source_p;
1744 moduledata.approved = 0;
1745
1746 call_hook(h_can_create_channel, &moduledata);
1747
1748 if(moduledata.approved != 0)
1749 {
1750 sendto_one(source_p, form_str(moduledata.approved),
1751 me.name, source_p->name, name);
1752 continue;
1753 }
1754
1755 if(splitmode && !IsOper(source_p) && (*name != '&') &&
1756 ConfigChannel.no_create_on_split)
1757 {
1758 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
1759 me.name, source_p->name, name);
1760 continue;
1761 }
1762
1763 flags = CHFL_CHANOP;
1764 }
1765
1766 if((rb_dlink_list_length(&source_p->user->channel) >=
1767 (unsigned long) ConfigChannel.max_chans_per_user) &&
1768 (!IsOper(source_p) ||
1769 (rb_dlink_list_length(&source_p->user->channel) >=
1770 (unsigned long) ConfigChannel.max_chans_per_user * 3)))
1771 {
1772 sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
1773 me.name, source_p->name, name);
67b90240
JH
1774 return;
1775 }
1776
67b90240
JH
1777 if(chptr == NULL) /* If I already have a chptr, no point doing this */
1778 {
1779 chptr = get_or_create_channel(source_p, name, NULL);
1780
1781 if(chptr == NULL)
1782 {
1783 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
1784 me.name, source_p->name, name);
67b90240
JH
1785 continue;
1786 }
1787 }
1788
67b90240
JH
1789 /* can_join checks for +i key, bans etc */
1790 if((i = can_join(source_p, chptr, key)))
1791 {
1792 if ((i != ERR_NEEDREGGEDNICK && i != ERR_THROTTLE && i != ERR_INVITEONLYCHAN && i != ERR_CHANNELISFULL) ||
1793 (!ConfigChannel.use_forward || (chptr = check_forward(source_p, chptr, key)) == NULL))
1794 {
1795 /* might be wrong, but is there any other better location for such?
1796 * see extensions/chm_operonly.c for other comments on this
1797 * -- dwr
1798 */
1799 if(i != ERR_CUSTOM)
1800 sendto_one(source_p, form_str(i), me.name, source_p->name, name);
1801
67b90240
JH
1802 continue;
1803 }
1804
1805 sendto_one_numeric(source_p, ERR_LINKCHANNEL, form_str(ERR_LINKCHANNEL), name, chptr->chname);
1806 }
aa35afbb
JH
1807
1808 if(flags == 0 &&
1809 !IsOper(source_p) && !IsExemptSpambot(source_p))
1810 check_spambot_warning(source_p, name);
67b90240
JH
1811
1812 /* add the user to the channel */
1813 add_user_to_channel(chptr, source_p, flags);
1814 if (chptr->mode.join_num &&
1815 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
1816 {
1817 chptr->join_count = 0;
1818 chptr->join_delta = rb_current_time();
1819 }
1820 chptr->join_count++;
1821
1822 /* we send the user their join here, because we could have to
1823 * send a mode out next.
1824 */
1825 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
1826 source_p->name,
1827 source_p->username, source_p->host, chptr->chname);
1828
1829 /* its a new channel, set +nt and burst. */
1830 if(flags & CHFL_CHANOP)
1831 {
1832 chptr->channelts = rb_current_time();
13ec57db
JH
1833
1834 /* autochanmodes stuff */
1835 if(ConfigChannel.autochanmodes)
1836 {
1837 char * ch;
1838 for(ch = ConfigChannel.autochanmodes; *ch; *ch++)
1839 {
1840 chptr->mode.mode |= chmode_table[*ch].mode_type;
1841 }
1842 }
1843 else
1844 {
1845 chptr->mode.mode |= MODE_TOPICLIMIT;
1846 chptr->mode.mode |= MODE_NOPRIVMSGS;
1847 }
1848
67b90240
JH
1849 modes = channel_modes(chptr, &me);
1850
1851 sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s %s",
1852 me.name, chptr->chname, modes);
1853
1854 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
1855 ":%s SJOIN %ld %s %s :@%s",
1856 me.id, (long) chptr->channelts,
1857 chptr->chname, modes, source_p->id);
1858 }
1859 else
1860 {
1861 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
1862 ":%s JOIN %ld %s +",
1863 use_id(source_p), (long) chptr->channelts,
1864 chptr->chname);
1865 }
1866
1867 del_invite(chptr, source_p);
1868
1869 if(chptr->topic != NULL)
1870 {
1871 sendto_one(source_p, form_str(RPL_TOPIC), me.name,
1872 source_p->name, chptr->chname, chptr->topic);
1873
1874 sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
1875 me.name, source_p->name, chptr->chname,
1876 chptr->topic_info, chptr->topic_time);
1877 }
1878
1879 channel_member_names(chptr, source_p, 1);
1880
67b90240
JH
1881 hook_info.client = source_p;
1882 hook_info.chptr = chptr;
1883 hook_info.key = key;
1884 call_hook(h_channel_join, &hook_info);
1885 }
1886
1887 return;
1888}