2 * ircd-ratbox: A slightly useful ircd.
3 * channel.c: Controls channels.
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
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.
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.
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
24 * $Id: channel.c 3580 2007-11-07 23:45:14Z jilles $
37 #include "s_serv.h" /* captab */
41 #include "s_conf.h" /* ConfigFileEntry, ConfigChannel */
42 #include "s_newconf.h"
46 struct config_channel_entry ConfigChannel
;
47 rb_dlink_list global_channel_list
;
48 static rb_bh
*channel_heap
;
49 static rb_bh
*ban_heap
;
50 static rb_bh
*topic_heap
;
51 static rb_bh
*member_heap
;
53 static int channel_capabs
[] = { CAP_EX
, CAP_IE
,
58 #define NCHCAPS (sizeof(channel_capabs)/sizeof(int))
59 #define NCHCAP_COMBOS (1 << NCHCAPS)
61 static struct ChCapCombo chcap_combos
[NCHCAP_COMBOS
];
63 static void free_topic(struct Channel
*chptr
);
65 static int h_can_join
;
66 static int h_can_create_channel
;
67 static int h_channel_join
;
73 * side effects - initialises the various blockheaps
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");
83 h_can_join
= register_hook("can_join");
84 h_channel_join
= register_hook("channel_join");
85 h_can_create_channel
= register_hook("can_create_channel");
89 * allocate_channel - Allocates a channel
92 allocate_channel(const char *chname
)
94 struct Channel
*chptr
;
95 chptr
= rb_bh_alloc(channel_heap
);
96 chptr
->chname
= rb_strdup(chname
);
101 free_channel(struct Channel
*chptr
)
103 rb_free(chptr
->chname
);
104 rb_bh_free(channel_heap
, chptr
);
108 allocate_ban(const char *banstr
, const char *who
)
111 bptr
= rb_bh_alloc(ban_heap
);
112 bptr
->banstr
= rb_strdup(banstr
);
113 bptr
->who
= rb_strdup(who
);
119 free_ban(struct Ban
*bptr
)
121 rb_free(bptr
->banstr
);
123 rb_bh_free(ban_heap
, bptr
);
127 /* find_channel_membership()
129 * input - channel to find them in, client to find
130 * output - membership of client in channel, else NULL
134 find_channel_membership(struct Channel
*chptr
, struct Client
*client_p
)
136 struct membership
*msptr
;
139 if(!IsClient(client_p
))
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
145 if(rb_dlink_list_length(&chptr
->members
) < rb_dlink_list_length(&client_p
->user
->channel
))
147 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
151 if(msptr
->client_p
== client_p
)
157 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
161 if(msptr
->chptr
== chptr
)
169 /* find_channel_status()
171 * input - membership to get status for, whether we can combine flags
172 * output - flags of user on channel
176 find_channel_status(struct membership
*msptr
, int combine
)
178 static char buffer
[5];
213 * input - membership to check for halfops
214 * output - 1 if the user is halfopped, 0 if the user is not or halfop
220 is_halfop(struct membership
*msptr
)
222 if(!ConfigChannel
.use_halfop
)
224 if(is_chmode_h(msptr
))
232 * input - membership to check for owner
233 * output - 1 if the user is an owner, 0 if the user is not or owner
239 is_owner(struct membership
*msptr
)
241 if(!ConfigChannel
.use_owner
)
243 if(is_chmode_a(msptr
))
251 * input - membership to check for ops
252 * output - 1 if the user is op, halfop, or owner, 0 elsewise
256 is_any_op(struct membership
*msptr
)
258 if(is_chanop(msptr
) || is_halfop(msptr
) || is_owner(msptr
))
264 /* is_chanop_voiced()
266 * input - memebership to check for status
267 * output - 1 if the user is op, halfop, owner, or voice, 0 elsewise
271 is_chanop_voiced(struct membership
*msptr
)
273 if(is_chanop(msptr
) || is_voiced(msptr
) || is_halfop(msptr
) || is_owner(msptr
))
281 * input - two memeberships
282 * output - 1 if the first memebership can kick/deop the second, 0 elsewise
286 can_kick_deop(struct membership
*source
, struct membership
*target
)
288 if(is_chanop(source
) && !is_owner(target
))
290 else if(is_halfop(source
) && !is_any_op(target
))
292 else if(is_owner(source
))
298 /* add_user_to_channel()
300 * input - channel to add client to, client to add, channel flags
302 * side effects - user is added to channel
305 add_user_to_channel(struct Channel
*chptr
, struct Client
*client_p
, int flags
)
307 struct membership
*msptr
;
309 s_assert(client_p
->user
!= NULL
);
310 if(client_p
->user
== NULL
)
313 msptr
= rb_bh_alloc(member_heap
);
315 msptr
->chptr
= chptr
;
316 msptr
->client_p
= client_p
;
317 msptr
->flags
= flags
;
319 rb_dlinkAdd(msptr
, &msptr
->usernode
, &client_p
->user
->channel
);
320 rb_dlinkAdd(msptr
, &msptr
->channode
, &chptr
->members
);
322 if(MyClient(client_p
))
323 rb_dlinkAdd(msptr
, &msptr
->locchannode
, &chptr
->locmembers
);
326 /* remove_user_from_channel()
328 * input - membership pointer to remove from channel
330 * side effects - membership (thus user) is removed from channel
333 remove_user_from_channel(struct membership
*msptr
)
335 struct Client
*client_p
;
336 struct Channel
*chptr
;
337 s_assert(msptr
!= NULL
);
341 client_p
= msptr
->client_p
;
342 chptr
= msptr
->chptr
;
344 rb_dlinkDelete(&msptr
->usernode
, &client_p
->user
->channel
);
345 rb_dlinkDelete(&msptr
->channode
, &chptr
->members
);
347 if(client_p
->servptr
== &me
)
348 rb_dlinkDelete(&msptr
->locchannode
, &chptr
->locmembers
);
350 if(!(chptr
->mode
.mode
& MODE_PERMANENT
) && rb_dlink_list_length(&chptr
->members
) <= 0)
351 destroy_channel(chptr
);
353 rb_bh_free(member_heap
, msptr
);
358 /* remove_user_from_channels()
360 * input - user to remove from all channels
362 * side effects - user is removed from all channels
365 remove_user_from_channels(struct Client
*client_p
)
367 struct Channel
*chptr
;
368 struct membership
*msptr
;
370 rb_dlink_node
*next_ptr
;
375 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, client_p
->user
->channel
.head
)
378 chptr
= msptr
->chptr
;
380 rb_dlinkDelete(&msptr
->channode
, &chptr
->members
);
382 if(client_p
->servptr
== &me
)
383 rb_dlinkDelete(&msptr
->locchannode
, &chptr
->locmembers
);
385 if(!(chptr
->mode
.mode
& MODE_PERMANENT
) && rb_dlink_list_length(&chptr
->members
) <= 0)
386 destroy_channel(chptr
);
388 rb_bh_free(member_heap
, msptr
);
391 client_p
->user
->channel
.head
= client_p
->user
->channel
.tail
= NULL
;
392 client_p
->user
->channel
.length
= 0;
395 /* invalidate_bancache_user()
397 * input - user to invalidate ban cache for
399 * side effects - ban cache is invalidated for all memberships of that user
400 * to be used after a nick change
403 invalidate_bancache_user(struct Client
*client_p
)
405 struct membership
*msptr
;
411 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
415 msptr
->flags
&= ~CHFL_BANNED
;
419 /* check_channel_name()
421 * input - channel name
422 * output - 1 if valid channel name, else 0
426 check_channel_name(const char *name
)
428 s_assert(name
!= NULL
);
432 for (; *name
; ++name
)
434 if(!IsChanChar(*name
))
441 /* free_channel_list()
443 * input - rb_dlink list to free
445 * side effects - list of b/e/I modes is cleared
448 free_channel_list(rb_dlink_list
* list
)
451 rb_dlink_node
*next_ptr
;
452 struct Ban
*actualBan
;
454 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, list
->head
)
456 actualBan
= ptr
->data
;
460 list
->head
= list
->tail
= NULL
;
466 * input - channel to destroy
468 * side effects - channel is obliterated
471 destroy_channel(struct Channel
*chptr
)
473 rb_dlink_node
*ptr
, *next_ptr
;
475 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->invites
.head
)
477 del_invite(chptr
, ptr
->data
);
480 /* free all bans/exceptions/denies */
481 free_channel_list(&chptr
->banlist
);
482 free_channel_list(&chptr
->exceptlist
);
483 free_channel_list(&chptr
->invexlist
);
484 free_channel_list(&chptr
->quietlist
);
489 rb_dlinkDelete(&chptr
->node
, &global_channel_list
);
490 del_from_channel_hash(chptr
->chname
, chptr
);
494 /* channel_pub_or_secret()
497 * output - "=" if public, "@" if secret, else "*"
501 channel_pub_or_secret(struct Channel
*chptr
)
503 if(PubChannel(chptr
))
505 else if(SecretChannel(chptr
))
510 /* channel_member_names()
512 * input - channel to list, client to list to, show endofnames
514 * side effects - client is given list of users on channel
517 channel_member_names(struct Channel
*chptr
, struct Client
*client_p
, int show_eon
)
519 struct membership
*msptr
;
520 struct Client
*target_p
;
528 int stack
= IsCapable(client_p
, CLICAP_MULTI_PREFIX
);
530 if(ShowChannel(client_p
, chptr
))
532 is_member
= IsMember(client_p
, chptr
);
534 cur_len
= mlen
= rb_sprintf(lbuf
, form_str(RPL_NAMREPLY
),
535 me
.name
, client_p
->name
,
536 channel_pub_or_secret(chptr
), chptr
->chname
);
540 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
543 target_p
= msptr
->client_p
;
545 if(IsInvisible(target_p
) && !is_member
)
548 /* space, possible "@+" prefix */
549 if(cur_len
+ strlen(target_p
->name
) + 3 >= BUFSIZE
- 3)
552 sendto_one(client_p
, "%s", lbuf
);
557 tlen
= rb_sprintf(t
, "%s%s ", find_channel_status(msptr
, stack
),
564 /* The old behaviour here was to always output our buffer,
565 * even if there are no clients we can show. This happens
566 * when a client does "NAMES" with no parameters, and all
567 * the clients on a -sp channel are +i. I dont see a good
568 * reason for keeping that behaviour, as it just wastes
574 sendto_one(client_p
, "%s", lbuf
);
579 sendto_one(client_p
, form_str(RPL_ENDOFNAMES
),
580 me
.name
, client_p
->name
, chptr
->chname
);
585 * input - channel to remove invite from, client to remove
587 * side effects - user is removed from invite list, if exists
590 del_invite(struct Channel
*chptr
, struct Client
*who
)
592 rb_dlinkFindDestroy(who
, &chptr
->invites
);
593 rb_dlinkFindDestroy(chptr
, &who
->user
->invited
);
598 * input - channel to check bans for, user to check bans against
599 * optional prebuilt buffers
600 * output - 1 if banned, else 0
604 is_banned(struct Channel
*chptr
, struct Client
*who
, struct membership
*msptr
,
605 const char *s
, const char *s2
)
607 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
608 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
609 char src_althost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
612 struct Ban
*actualBan
= NULL
;
613 struct Ban
*actualExcept
= NULL
;
618 /* if the buffers havent been built, do it here */
621 rb_sprintf(src_host
, "%s!%s@%s", who
->name
, who
->username
, who
->host
);
622 rb_sprintf(src_iphost
, "%s!%s@%s", who
->name
, who
->username
, who
->sockhost
);
627 if(who
->localClient
->mangledhost
!= NULL
)
629 /* if host mangling mode enabled, also check their real host */
630 if(!strcmp(who
->host
, who
->localClient
->mangledhost
))
632 rb_sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->orighost
);
635 /* if host mangling mode not enabled and no other spoof,
636 * also check the mangled form of their host */
637 else if (!IsDynSpoof(who
))
639 rb_sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->localClient
->mangledhost
);
644 RB_DLINK_FOREACH(ptr
, chptr
->banlist
.head
)
646 actualBan
= ptr
->data
;
647 if(match(actualBan
->banstr
, s
) ||
648 match(actualBan
->banstr
, s2
) ||
649 match_cidr(actualBan
->banstr
, s2
) ||
650 match_extban(actualBan
->banstr
, who
, chptr
, CHFL_BAN
) ||
651 (s3
!= NULL
&& match(actualBan
->banstr
, s3
)))
657 if((actualBan
!= NULL
) && ConfigChannel
.use_except
)
659 RB_DLINK_FOREACH(ptr
, chptr
->exceptlist
.head
)
661 actualExcept
= ptr
->data
;
663 /* theyre exempted.. */
664 if(match(actualExcept
->banstr
, s
) ||
665 match(actualExcept
->banstr
, s2
) ||
666 match_cidr(actualExcept
->banstr
, s2
) ||
667 match_extban(actualExcept
->banstr
, who
, chptr
, CHFL_EXCEPTION
) ||
668 (s3
!= NULL
&& match(actualExcept
->banstr
, s3
)))
670 /* cache the fact theyre not banned */
673 msptr
->bants
= chptr
->bants
;
674 msptr
->flags
&= ~CHFL_BANNED
;
677 return CHFL_EXCEPTION
;
682 /* cache the banned/not banned status */
685 msptr
->bants
= chptr
->bants
;
687 if(actualBan
!= NULL
)
689 msptr
->flags
|= CHFL_BANNED
;
694 msptr
->flags
&= ~CHFL_BANNED
;
699 return ((actualBan
? CHFL_BAN
: 0));
704 * input - channel to check bans for, user to check bans against
705 * optional prebuilt buffers
706 * output - 1 if banned, else 0
710 is_quieted(struct Channel
*chptr
, struct Client
*who
, struct membership
*msptr
,
711 const char *s
, const char *s2
)
713 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
714 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
715 char src_althost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
718 struct Ban
*actualBan
= NULL
;
719 struct Ban
*actualExcept
= NULL
;
724 /* if the buffers havent been built, do it here */
727 rb_sprintf(src_host
, "%s!%s@%s", who
->name
, who
->username
, who
->host
);
728 rb_sprintf(src_iphost
, "%s!%s@%s", who
->name
, who
->username
, who
->sockhost
);
733 if(who
->localClient
->mangledhost
!= NULL
)
735 /* if host mangling mode enabled, also check their real host */
736 if(!strcmp(who
->host
, who
->localClient
->mangledhost
))
738 rb_sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->orighost
);
741 /* if host mangling mode not enabled and no other spoof,
742 * also check the mangled form of their host */
743 else if (!IsDynSpoof(who
))
745 rb_sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->localClient
->mangledhost
);
750 RB_DLINK_FOREACH(ptr
, chptr
->quietlist
.head
)
752 actualBan
= ptr
->data
;
753 if(match(actualBan
->banstr
, s
) ||
754 match(actualBan
->banstr
, s2
) ||
755 match_cidr(actualBan
->banstr
, s2
) ||
756 match_extban(actualBan
->banstr
, who
, chptr
, CHFL_QUIET
) ||
757 (s3
!= NULL
&& match(actualBan
->banstr
, s3
)))
763 if((actualBan
!= NULL
) && ConfigChannel
.use_except
)
765 RB_DLINK_FOREACH(ptr
, chptr
->exceptlist
.head
)
767 actualExcept
= ptr
->data
;
769 /* theyre exempted.. */
770 if(match(actualExcept
->banstr
, s
) ||
771 match(actualExcept
->banstr
, s2
) ||
772 match_cidr(actualExcept
->banstr
, s2
) ||
773 match_extban(actualExcept
->banstr
, who
, chptr
, CHFL_EXCEPTION
) ||
774 (s3
!= NULL
&& match(actualExcept
->banstr
, s3
)))
776 /* cache the fact theyre not banned */
779 msptr
->bants
= chptr
->bants
;
780 msptr
->flags
&= ~CHFL_BANNED
;
783 return CHFL_EXCEPTION
;
788 /* cache the banned/not banned status */
791 msptr
->bants
= chptr
->bants
;
793 if(actualBan
!= NULL
)
795 msptr
->flags
|= CHFL_BANNED
;
800 msptr
->flags
&= ~CHFL_BANNED
;
805 return ((actualBan
? CHFL_BAN
: 0));
810 * input - client to check, channel to check for, key
811 * output - reason for not being able to join, else 0
815 can_join(struct Client
*source_p
, struct Channel
*chptr
, char *key
)
817 rb_dlink_node
*invite
= NULL
;
819 struct Ban
*invex
= NULL
;
820 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
821 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
822 char src_althost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
825 hook_data_channel moduledata
;
827 s_assert(source_p
->localClient
!= NULL
);
829 if(IsOverride(source_p
))
832 rb_sprintf(src_host
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->host
);
833 rb_sprintf(src_iphost
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->sockhost
);
834 if(source_p
->localClient
->mangledhost
!= NULL
)
836 /* if host mangling mode enabled, also check their real host */
837 if(!strcmp(source_p
->host
, source_p
->localClient
->mangledhost
))
839 rb_sprintf(src_althost
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->orighost
);
842 /* if host mangling mode not enabled and no other spoof,
843 * also check the mangled form of their host */
844 else if (!IsDynSpoof(source_p
))
846 rb_sprintf(src_althost
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->localClient
->mangledhost
);
851 if((is_banned(chptr
, source_p
, NULL
, src_host
, src_iphost
)) == CHFL_BAN
)
852 return (ERR_BANNEDFROMCHAN
);
854 if(chptr
->mode
.mode
& MODE_INVITEONLY
)
856 RB_DLINK_FOREACH(invite
, source_p
->user
->invited
.head
)
858 if(invite
->data
== chptr
)
863 if(!ConfigChannel
.use_invex
)
864 return (ERR_INVITEONLYCHAN
);
865 RB_DLINK_FOREACH(ptr
, chptr
->invexlist
.head
)
868 if(match(invex
->banstr
, src_host
)
869 || match(invex
->banstr
, src_iphost
)
870 || match_cidr(invex
->banstr
, src_iphost
)
871 || match_extban(invex
->banstr
, source_p
, chptr
, CHFL_INVEX
)
872 || (use_althost
&& match(invex
->banstr
, src_althost
)))
876 return (ERR_INVITEONLYCHAN
);
880 if(*chptr
->mode
.key
&& (EmptyString(key
) || irccmp(chptr
->mode
.key
, key
)))
881 return (ERR_BADCHANNELKEY
);
883 if(chptr
->mode
.limit
&&
884 rb_dlink_list_length(&chptr
->members
) >= (unsigned long) chptr
->mode
.limit
)
885 i
= ERR_CHANNELISFULL
;
886 if(chptr
->mode
.mode
& MODE_REGONLY
&& EmptyString(source_p
->user
->suser
))
887 i
= ERR_NEEDREGGEDNICK
;
888 /* join throttling stuff --nenolod */
889 else if(chptr
->mode
.join_num
> 0 && chptr
->mode
.join_time
> 0)
891 if ((rb_current_time() - chptr
->join_delta
<=
892 chptr
->mode
.join_time
) && (chptr
->join_count
>=
893 chptr
->mode
.join_num
))
897 /* allow /invite to override +l/+r/+j also -- jilles */
898 if (i
!= 0 && invite
== NULL
)
900 RB_DLINK_FOREACH(invite
, source_p
->user
->invited
.head
)
902 if(invite
->data
== chptr
)
909 moduledata
.client
= source_p
;
910 moduledata
.chptr
= chptr
;
911 moduledata
.approved
= 0;
913 call_hook(h_can_join
, &moduledata
);
915 return moduledata
.approved
;
920 * input - user to check in channel, membership pointer
921 * output - whether can explicitly send or not, else CAN_SEND_NONOP
925 can_send(struct Channel
*chptr
, struct Client
*source_p
, struct membership
*msptr
)
927 if(IsServer(source_p
) || IsService(source_p
))
930 if(MyClient(source_p
) && hash_find_resv(chptr
->chname
) &&
931 !IsOper(source_p
) && !IsExemptResv(source_p
))
936 msptr
= find_channel_membership(chptr
, source_p
);
940 /* if its +m or +n and theyre not in the channel,
941 * they cant send. we dont check bans here because
942 * theres no possibility of caching them --fl
944 if(chptr
->mode
.mode
& MODE_NOPRIVMSGS
|| chptr
->mode
.mode
& MODE_MODERATED
)
947 return CAN_SEND_NONOP
;
951 if(is_chanop_voiced(msptr
))
954 if(IsOverride(source_p
))
955 return CAN_SEND_NONOP
;
957 if(chptr
->mode
.mode
& MODE_MODERATED
)
960 if(MyClient(source_p
))
962 /* cached can_send */
963 if(msptr
->bants
== chptr
->bants
)
965 if(can_send_banned(msptr
))
968 else if(is_banned(chptr
, source_p
, msptr
, NULL
, NULL
) == CHFL_BAN
969 || is_quieted(chptr
, source_p
, msptr
, NULL
, NULL
) == CHFL_BAN
)
973 return CAN_SEND_NONOP
;
976 /* find_bannickchange_channel()
977 * Input: client to check
978 * Output: channel preventing nick change
981 find_bannickchange_channel(struct Client
*client_p
)
983 struct Channel
*chptr
;
984 struct membership
*msptr
;
986 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
987 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
989 if (!MyClient(client_p
) || IsOverride(client_p
))
992 rb_sprintf(src_host
, "%s!%s@%s", client_p
->name
, client_p
->username
, client_p
->host
);
993 rb_sprintf(src_iphost
, "%s!%s@%s", client_p
->name
, client_p
->username
, client_p
->sockhost
);
995 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
998 chptr
= msptr
->chptr
;
999 if (is_chanop_voiced(msptr
))
1001 /* cached can_send */
1002 if (msptr
->bants
== chptr
->bants
)
1004 if (can_send_banned(msptr
))
1007 else if (is_banned(chptr
, client_p
, msptr
, src_host
, src_iphost
) == CHFL_BAN
1008 || is_quieted(chptr
, client_p
, msptr
, src_host
, src_iphost
) == CHFL_BAN
)
1014 /* find_nonickchange_channel()
1015 * Input: client to check
1016 * Output: channel preventing nick change
1019 find_nonickchange_channel(struct Client
*client_p
)
1021 struct Channel
*chptr
;
1022 struct membership
*msptr
;
1025 if (!MyClient(client_p
))
1028 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
1031 chptr
= msptr
->chptr
;
1032 if (chptr
->mode
.mode
& MODE_NONICK
&& (!ConfigChannel
.exempt_cmode_N
|| !is_any_op(msptr
)))
1038 /* void check_spambot_warning(struct Client *source_p)
1039 * Input: Client to check, channel name or NULL if this is a part.
1041 * Side-effects: Updates the client's oper_warn_count_down, warns the
1042 * IRC operators if necessary, and updates join_leave_countdown as
1046 check_spambot_warning(struct Client
*source_p
, const char *name
)
1049 int decrement_count
;
1050 if((GlobalSetOptions
.spam_num
&&
1051 (source_p
->localClient
->join_leave_count
>= GlobalSetOptions
.spam_num
)))
1053 if(source_p
->localClient
->oper_warn_count_down
> 0)
1054 source_p
->localClient
->oper_warn_count_down
--;
1056 source_p
->localClient
->oper_warn_count_down
= 0;
1057 if(source_p
->localClient
->oper_warn_count_down
== 0 &&
1060 /* Its already known as a possible spambot */
1061 sendto_realops_snomask(SNO_BOTS
, L_NETWIDE
,
1062 "User %s (%s@%s) trying to join %s is a possible spambot",
1064 source_p
->username
, source_p
->orighost
, name
);
1065 source_p
->localClient
->oper_warn_count_down
= OPER_SPAM_COUNTDOWN
;
1071 (rb_current_time() - source_p
->localClient
->last_leave_time
)) >
1072 JOIN_LEAVE_COUNT_EXPIRE_TIME
)
1074 decrement_count
= (t_delta
/ JOIN_LEAVE_COUNT_EXPIRE_TIME
);
1077 else if(decrement_count
> source_p
->localClient
->join_leave_count
)
1078 source_p
->localClient
->join_leave_count
= 0;
1080 source_p
->localClient
->join_leave_count
-= decrement_count
;
1084 if((rb_current_time() -
1085 (source_p
->localClient
->last_join_time
)) < GlobalSetOptions
.spam_time
)
1087 /* oh, its a possible spambot */
1088 source_p
->localClient
->join_leave_count
++;
1092 source_p
->localClient
->last_join_time
= rb_current_time();
1094 source_p
->localClient
->last_leave_time
= rb_current_time();
1098 /* check_splitmode()
1102 * side effects - compares usercount and servercount against their split
1103 * values and adjusts splitmode accordingly
1106 check_splitmode(void *unused
)
1108 if(splitchecking
&& (ConfigChannel
.no_join_on_split
|| ConfigChannel
.no_create_on_split
))
1110 /* not split, we're being asked to check now because someone
1115 if(eob_count
< split_servers
|| Count
.total
< split_users
)
1118 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1119 "Network split, activating splitmode");
1120 check_splitmode_ev
= rb_event_addish("check_splitmode", check_splitmode
, NULL
, 2);
1123 /* in splitmode, check whether its finished */
1124 else if(eob_count
>= split_servers
&& Count
.total
>= split_users
)
1128 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1129 "Network rejoined, deactivating splitmode");
1131 rb_event_delete(check_splitmode_ev
);
1132 check_splitmode_ev
= NULL
;
1140 * input - channel to allocate topic for
1141 * output - 1 on success, else 0
1142 * side effects - channel gets a topic allocated
1145 allocate_topic(struct Channel
*chptr
)
1152 ptr
= rb_bh_alloc(topic_heap
);
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
1159 chptr
->topic_info
= (char *) ptr
+ TOPICLEN
+ 1;
1160 *chptr
->topic
= '\0';
1161 *chptr
->topic_info
= '\0';
1166 * input - channel which has topic to free
1168 * side effects - channels topic is free'd
1171 free_topic(struct Channel
*chptr
)
1175 if(chptr
== NULL
|| chptr
->topic
== NULL
)
1178 /* This is safe for now - If you change allocate_topic you
1179 * MUST change this as well
1182 rb_bh_free(topic_heap
, ptr
);
1183 chptr
->topic
= NULL
;
1184 chptr
->topic_info
= NULL
;
1187 /* set_channel_topic()
1189 * input - channel, topic to set, topic info and topic ts
1191 * side effects - channels topic, topic info and TS are set.
1194 set_channel_topic(struct Channel
*chptr
, const char *topic
, const char *topic_info
, time_t topicts
)
1196 if(strlen(topic
) > 0)
1198 if(chptr
->topic
== NULL
)
1199 allocate_topic(chptr
);
1200 rb_strlcpy(chptr
->topic
, topic
, TOPICLEN
+ 1);
1201 rb_strlcpy(chptr
->topic_info
, topic_info
, USERHOST_REPLYLEN
);
1202 chptr
->topic_time
= topicts
;
1206 if(chptr
->topic
!= NULL
)
1208 chptr
->topic_time
= 0;
1212 /* has_common_channel()
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
1220 has_common_channel(struct Client
*client1
, struct Client
*client2
)
1224 RB_DLINK_FOREACH(ptr
, client1
->user
->channel
.head
)
1226 if(IsMember(client2
, ((struct membership
*)ptr
->data
)->chptr
))
1234 * inputs - pointer to channel
1235 * - pointer to client
1236 * output - string with simple modes
1237 * side effects - result from previous calls overwritten
1239 * Stolen from ShadowIRCd 4 --nenolod
1242 channel_modes(struct Channel
*chptr
, struct Client
*client_p
)
1247 static char final
[BUFSIZE
];
1254 for (i
= 0; i
< 256; i
++)
1256 if(chmode_table
[i
].set_func
== chm_hidden
&& !IsOper(client_p
) && IsClient(client_p
))
1258 if(chptr
->mode
.mode
& chmode_flags
[i
])
1262 if(chptr
->mode
.limit
)
1266 if(!IsClient(client_p
) || IsMember(client_p
, chptr
))
1267 pbuf
+= rb_sprintf(pbuf
, " %d", chptr
->mode
.limit
);
1270 if(*chptr
->mode
.key
)
1274 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1275 pbuf
+= rb_sprintf(pbuf
, " %s", chptr
->mode
.key
);
1278 if(chptr
->mode
.join_num
)
1282 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1283 pbuf
+= rb_sprintf(pbuf
, " %d:%d", chptr
->mode
.join_num
,
1284 chptr
->mode
.join_time
);
1287 if(*chptr
->mode
.forward
&& (ConfigChannel
.use_forward
|| !IsClient(client_p
)))
1291 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1292 pbuf
+= rb_sprintf(pbuf
, " %s", chptr
->mode
.forward
);
1297 rb_strlcpy(final
, buf1
, sizeof final
);
1298 rb_strlcat(final
, buf2
, sizeof final
);
1302 /* Now lets do some stuff to keep track of what combinations of
1304 * Note that the number of combinations doubles each time you add
1305 * something to this list. Each one is only quick if no servers use that
1306 * combination, but if the numbers get too high here MODE will get too
1307 * slow. I suggest if you get more than 7 here, you consider getting rid
1308 * of some and merging or something. If it wasn't for irc+cs we would
1309 * probably not even need to bother about most of these, but unfortunately
1313 /* void init_chcap_usage_counts(void)
1317 * Side-effects - Initialises the usage counts to zero. Fills in the
1318 * chcap_yes and chcap_no combination tables.
1321 init_chcap_usage_counts(void)
1323 unsigned long m
, c
, y
, n
;
1325 memset(chcap_combos
, 0, sizeof(chcap_combos
));
1327 /* For every possible combination */
1328 for (m
= 0; m
< NCHCAP_COMBOS
; m
++)
1330 /* Check each capab */
1331 for (c
= y
= n
= 0; c
< NCHCAPS
; c
++)
1333 if((m
& (1 << c
)) == 0)
1334 n
|= channel_capabs
[c
];
1336 y
|= channel_capabs
[c
];
1338 chcap_combos
[m
].cap_yes
= y
;
1339 chcap_combos
[m
].cap_no
= n
;
1343 /* void set_chcap_usage_counts(struct Client *serv_p)
1344 * Input: serv_p; The client whose capabs to register.
1346 * Side-effects: Increments the usage counts for the correct capab
1350 set_chcap_usage_counts(struct Client
*serv_p
)
1354 for (n
= 0; n
< NCHCAP_COMBOS
; n
++)
1356 if(IsCapable(serv_p
, chcap_combos
[n
].cap_yes
) &&
1357 NotCapable(serv_p
, chcap_combos
[n
].cap_no
))
1359 chcap_combos
[n
].count
++;
1364 /* This should be impossible -A1kmm. */
1368 /* void set_chcap_usage_counts(struct Client *serv_p)
1370 * Inputs - serv_p; The client whose capabs to register.
1372 * Side-effects - Decrements the usage counts for the correct capab
1376 unset_chcap_usage_counts(struct Client
*serv_p
)
1380 for (n
= 0; n
< NCHCAP_COMBOS
; n
++)
1382 if(IsCapable(serv_p
, chcap_combos
[n
].cap_yes
) &&
1383 NotCapable(serv_p
, chcap_combos
[n
].cap_no
))
1385 /* Hopefully capabs can't change dynamically or anything... */
1386 s_assert(chcap_combos
[n
].count
> 0);
1388 if(chcap_combos
[n
].count
> 0)
1389 chcap_combos
[n
].count
--;
1394 /* This should be impossible -A1kmm. */
1398 /* void send_cap_mode_changes(struct Client *client_p,
1399 * struct Client *source_p,
1400 * struct Channel *chptr, int cap, int nocap)
1401 * Input: The client sending(client_p), the source client(source_p),
1402 * the channel to send mode changes for(chptr)
1404 * Side-effects: Sends the appropriate mode changes to capable servers.
1406 * Reverted back to my original design, except that we now keep a count
1407 * of the number of servers which each combination as an optimisation, so
1408 * the capabs combinations which are not needed are not worked out. -A1kmm
1411 send_cap_mode_changes(struct Client
*client_p
, struct Client
*source_p
,
1412 struct Channel
*chptr
, struct ChModeChange mode_changes
[], int mode_count
)
1414 static char modebuf
[BUFSIZE
];
1415 static char parabuf
[BUFSIZE
];
1416 int i
, mbl
, pbl
, nc
, mc
, preflen
, len
;
1425 /* Now send to servers... */
1426 for (j
= 0; j
< NCHCAP_COMBOS
; j
++)
1428 if(chcap_combos
[j
].count
== 0)
1438 cap
= chcap_combos
[j
].cap_yes
;
1439 nocap
= chcap_combos
[j
].cap_no
;
1441 mbl
= preflen
= rb_sprintf(modebuf
, ":%s TMODE %ld %s ",
1442 use_id(source_p
), (long) chptr
->channelts
,
1445 /* loop the list of - modes we have */
1446 for (i
= 0; i
< mode_count
; i
++)
1448 /* if they dont support the cap we need, or they do support a cap they
1449 * cant have, then dont add it to the modebuf.. that way they wont see
1452 if((mode_changes
[i
].letter
== 0) ||
1453 ((cap
& mode_changes
[i
].caps
) != mode_changes
[i
].caps
)
1454 || ((nocap
& mode_changes
[i
].nocaps
) != mode_changes
[i
].nocaps
))
1457 if(!EmptyString(mode_changes
[i
].id
))
1458 arg
= mode_changes
[i
].id
;
1460 arg
= mode_changes
[i
].arg
;
1464 arglen
= strlen(arg
);
1466 /* dont even think about it! --fl */
1467 if(arglen
> MODEBUFLEN
- 5)
1471 /* if we're creeping past the buf size, we need to send it and make
1472 * another line for the other modes
1473 * XXX - this could give away server topology with uids being
1474 * different lengths, but not much we can do, except possibly break
1475 * them as if they were the longest of the nick or uid at all times,
1476 * which even then won't work as we don't always know the uid -A1kmm.
1478 if(arg
&& ((mc
== MAXMODEPARAMSSERV
) ||
1479 ((mbl
+ pbl
+ arglen
+ 4) > (BUFSIZE
- 3))))
1482 sendto_server(client_p
, chptr
, cap
, nocap
,
1483 "%s %s", modebuf
, parabuf
);
1494 if(dir
!= mode_changes
[i
].dir
)
1496 modebuf
[mbl
++] = (mode_changes
[i
].dir
== MODE_ADD
) ? '+' : '-';
1497 dir
= mode_changes
[i
].dir
;
1500 modebuf
[mbl
++] = mode_changes
[i
].letter
;
1506 len
= rb_sprintf(pbuf
, "%s ", arg
);
1513 if(pbl
&& parabuf
[pbl
- 1] == ' ')
1514 parabuf
[pbl
- 1] = 0;
1517 sendto_server(client_p
, chptr
, cap
, nocap
, "%s %s", modebuf
, parabuf
);
1521 /* Check what we will forward to, without sending any notices to the user
1525 check_forward(struct Client
*source_p
, struct Channel
*chptr
,
1531 if (IsNoForward(source_p
))
1536 chptr
= find_channel(chptr
->mode
.forward
);
1537 /* Can only forward to existing channels */
1540 /* Already on there, show original error message */
1541 if (IsMember(source_p
, chptr
))
1543 /* Juped. Sending a warning notice would be unfair */
1544 if (hash_find_resv(chptr
->chname
))
1546 /* Don't forward to +Q channel */
1547 if (chptr
->mode
.mode
& MODE_DISFORWARD
)
1549 i
= can_join(source_p
, chptr
, key
);
1552 if (i
!= ERR_INVITEONLYCHAN
&& i
!= ERR_NEEDREGGEDNICK
&& i
!= ERR_THROTTLE
&& i
!= ERR_CHANNELISFULL
)
1563 * inputs - pointer to client doing join 0
1565 * side effects - Use has decided to join 0. This is legacy
1566 * from the days when channels were numbers not names. *sigh*
1569 do_join_0(struct Client
*client_p
, struct Client
*source_p
)
1571 struct membership
*msptr
;
1572 struct Channel
*chptr
= NULL
;
1575 /* Finish the flood grace period... */
1576 if(MyClient(source_p
) && !IsFloodDone(source_p
))
1577 flood_endgrace(source_p
);
1579 sendto_server(client_p
, NULL
, CAP_TS6
, NOCAPS
, ":%s JOIN 0", use_id(source_p
));
1581 while((ptr
= source_p
->user
->channel
.head
))
1583 if(source_p
->user
->channel
.head
&& MyConnect(source_p
) &&
1584 !IsOper(source_p
) && !IsExemptSpambot(source_p
))
1585 check_spambot_warning(source_p
, NULL
);
1588 chptr
= msptr
->chptr
;
1589 sendto_channel_local(ALL_MEMBERS
, chptr
, ":%s!%s@%s PART %s",
1591 source_p
->username
, source_p
->host
, chptr
->chname
);
1592 remove_user_from_channel(msptr
);
1597 check_channel_name_loc(struct Client
*source_p
, const char *name
)
1601 s_assert(name
!= NULL
);
1602 if(EmptyString(name
))
1605 if(ConfigFileEntry
.disable_fake_channels
&& !IsOper(source_p
))
1607 for(p
= name
; *p
; ++p
)
1609 if(!IsChanChar(*p
) || IsFakeChanChar(*p
))
1615 for(p
= name
; *p
; ++p
)
1622 if(ConfigChannel
.only_ascii_channels
)
1624 for(p
= name
; *p
; ++p
)
1625 if(*p
< 33 || *p
> 126)
1633 void user_join(struct Client
* client_p
, struct Client
* source_p
, const char * channels
, const char * keys
)
1635 static char jbuf
[BUFSIZE
];
1636 struct Channel
*chptr
= NULL
;
1637 struct ConfItem
*aconf
;
1642 char *p
= NULL
, *p2
= NULL
;
1648 if(channels
== NULL
)
1651 /* rebuild the list of channels theyre supposed to be joining.
1652 * this code has a side effect of losing keys, but..
1654 chanlist
= LOCAL_COPY(channels
);
1655 for(name
= rb_strtok_r(chanlist
, ",", &p
); name
; name
= rb_strtok_r(NULL
, ",", &p
))
1657 /* check the length and name of channel is ok */
1658 if(!check_channel_name_loc(source_p
, name
) || (strlen(name
) > LOC_CHANNELLEN
))
1660 sendto_one_numeric(source_p
, ERR_BADCHANNAME
,
1661 form_str(ERR_BADCHANNAME
), (unsigned char *) name
);
1665 /* join 0 parts all channels */
1666 if(*name
== '0' && (name
[1] == ',' || name
[1] == '\0') && name
== chanlist
)
1668 (void) strcpy(jbuf
, "0");
1672 /* check it begins with # or &, and local chans are disabled */
1673 else if(!IsChannelName(name
) ||
1674 ( !ConfigChannel
.use_local_channels
&& name
[0] == '&'))
1676 sendto_one_numeric(source_p
, ERR_NOSUCHCHANNEL
,
1677 form_str(ERR_NOSUCHCHANNEL
), name
);
1681 /* see if its resv'd */
1682 if(!IsExemptResv(source_p
) && (aconf
= hash_find_resv(name
)))
1684 sendto_one_numeric(source_p
, ERR_BADCHANNAME
,
1685 form_str(ERR_BADCHANNAME
), name
);
1687 /* dont warn for opers */
1688 if(!IsExemptJupe(source_p
) && !IsOper(source_p
))
1689 sendto_realops_snomask(SNO_SPY
, L_NETWIDE
,
1690 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
1691 source_p
->name
, source_p
->username
,
1692 source_p
->orighost
, name
, aconf
->passwd
);
1693 /* dont update tracking for jupe exempt users, these
1694 * are likely to be spamtrap leaves
1696 else if(IsExemptJupe(source_p
))
1702 if(splitmode
&& !IsOper(source_p
) && (*name
!= '&') &&
1703 ConfigChannel
.no_join_on_split
)
1705 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
1706 me
.name
, source_p
->name
, name
);
1711 (void) strcat(jbuf
, ",");
1712 (void) rb_strlcat(jbuf
, name
, sizeof(jbuf
));
1717 mykey
= LOCAL_COPY(keys
);
1718 key
= rb_strtok_r(mykey
, ",", &p2
);
1721 for(name
= rb_strtok_r(jbuf
, ",", &p
); name
;
1722 key
= (key
) ? rb_strtok_r(NULL
, ",", &p2
) : NULL
, name
= rb_strtok_r(NULL
, ",", &p
))
1724 hook_data_channel_activity hook_info
;
1726 /* JOIN 0 simply parts all channels the user is in */
1727 if(*name
== '0' && !atoi(name
))
1729 if(source_p
->user
->channel
.head
== NULL
)
1732 do_join_0(&me
, source_p
);
1736 /* look for the channel */
1737 if((chptr
= find_channel(name
)) != NULL
)
1739 if(IsMember(source_p
, chptr
))
1746 hook_data_client_approval moduledata
;
1748 moduledata
.client
= source_p
;
1749 moduledata
.approved
= 0;
1751 call_hook(h_can_create_channel
, &moduledata
);
1753 if(moduledata
.approved
!= 0)
1755 sendto_one(source_p
, form_str(moduledata
.approved
),
1756 me
.name
, source_p
->name
, name
);
1760 if(splitmode
&& !IsOper(source_p
) && (*name
!= '&') &&
1761 ConfigChannel
.no_create_on_split
)
1763 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
1764 me
.name
, source_p
->name
, name
);
1768 flags
= CHFL_CHANOP
;
1771 if((rb_dlink_list_length(&source_p
->user
->channel
) >=
1772 (unsigned long) ConfigChannel
.max_chans_per_user
) &&
1773 (!IsOper(source_p
) ||
1774 (rb_dlink_list_length(&source_p
->user
->channel
) >=
1775 (unsigned long) ConfigChannel
.max_chans_per_user
* 3)))
1777 sendto_one(source_p
, form_str(ERR_TOOMANYCHANNELS
),
1778 me
.name
, source_p
->name
, name
);
1782 if(chptr
== NULL
) /* If I already have a chptr, no point doing this */
1784 chptr
= get_or_create_channel(source_p
, name
, NULL
);
1788 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
1789 me
.name
, source_p
->name
, name
);
1794 /* can_join checks for +i key, bans etc */
1795 if((i
= can_join(source_p
, chptr
, key
)))
1797 if ((i
!= ERR_NEEDREGGEDNICK
&& i
!= ERR_THROTTLE
&& i
!= ERR_INVITEONLYCHAN
&& i
!= ERR_CHANNELISFULL
) ||
1798 (!ConfigChannel
.use_forward
|| (chptr
= check_forward(source_p
, chptr
, key
)) == NULL
))
1800 /* might be wrong, but is there any other better location for such?
1801 * see extensions/chm_operonly.c for other comments on this
1805 sendto_one(source_p
, form_str(i
), me
.name
, source_p
->name
, name
);
1810 sendto_one_numeric(source_p
, ERR_LINKCHANNEL
, form_str(ERR_LINKCHANNEL
), name
, chptr
->chname
);
1814 !IsOper(source_p
) && !IsExemptSpambot(source_p
))
1815 check_spambot_warning(source_p
, name
);
1817 /* add the user to the channel */
1818 add_user_to_channel(chptr
, source_p
, flags
);
1819 if (chptr
->mode
.join_num
&&
1820 rb_current_time() - chptr
->join_delta
>= chptr
->mode
.join_time
)
1822 chptr
->join_count
= 0;
1823 chptr
->join_delta
= rb_current_time();
1825 chptr
->join_count
++;
1827 /* we send the user their join here, because we could have to
1828 * send a mode out next.
1830 sendto_channel_local(ALL_MEMBERS
, chptr
, ":%s!%s@%s JOIN :%s",
1832 source_p
->username
, source_p
->host
, chptr
->chname
);
1834 /* its a new channel, set +nt and burst. */
1835 if(flags
& CHFL_CHANOP
)
1837 chptr
->channelts
= rb_current_time();
1839 /* autochanmodes stuff */
1840 if(ConfigChannel
.autochanmodes
)
1843 for(ch
= ConfigChannel
.autochanmodes
; *ch
; *ch
++)
1845 chptr
->mode
.mode
|= chmode_table
[*ch
].mode_type
;
1850 chptr
->mode
.mode
|= MODE_TOPICLIMIT
;
1851 chptr
->mode
.mode
|= MODE_NOPRIVMSGS
;
1854 modes
= channel_modes(chptr
, &me
);
1856 sendto_channel_local(ONLY_CHANOPS
, chptr
, ":%s MODE %s %s",
1857 me
.name
, chptr
->chname
, modes
);
1859 sendto_server(client_p
, chptr
, CAP_TS6
, NOCAPS
,
1860 ":%s SJOIN %ld %s %s :@%s",
1861 me
.id
, (long) chptr
->channelts
,
1862 chptr
->chname
, modes
, source_p
->id
);
1866 sendto_server(client_p
, chptr
, CAP_TS6
, NOCAPS
,
1867 ":%s JOIN %ld %s +",
1868 use_id(source_p
), (long) chptr
->channelts
,
1872 del_invite(chptr
, source_p
);
1874 if(chptr
->topic
!= NULL
)
1876 sendto_one(source_p
, form_str(RPL_TOPIC
), me
.name
,
1877 source_p
->name
, chptr
->chname
, chptr
->topic
);
1879 sendto_one(source_p
, form_str(RPL_TOPICWHOTIME
),
1880 me
.name
, source_p
->name
, chptr
->chname
,
1881 chptr
->topic_info
, chptr
->topic_time
);
1884 channel_member_names(chptr
, source_p
, 1);
1886 hook_info
.client
= source_p
;
1887 hook_info
.chptr
= chptr
;
1888 hook_info
.key
= key
;
1889 call_hook(h_channel_join
, &hook_info
);