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