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
34 #include "s_serv.h" /* captab */
38 #include "s_conf.h" /* ConfigFileEntry, ConfigChannel */
39 #include "s_newconf.h"
43 struct config_channel_entry ConfigChannel
;
44 rb_dlink_list global_channel_list
;
45 static rb_bh
*channel_heap
;
46 static rb_bh
*ban_heap
;
47 static rb_bh
*topic_heap
;
48 static rb_bh
*member_heap
;
50 static void free_topic(struct Channel
*chptr
);
52 static int h_can_join
;
53 static int h_can_send
;
54 int h_get_channel_access
;
60 * side effects - initialises the various blockheaps
65 channel_heap
= rb_bh_create(sizeof(struct Channel
), CHANNEL_HEAP_SIZE
, "channel_heap");
66 ban_heap
= rb_bh_create(sizeof(struct Ban
), BAN_HEAP_SIZE
, "ban_heap");
67 topic_heap
= rb_bh_create(TOPICLEN
+ 1 + USERHOST_REPLYLEN
, TOPIC_HEAP_SIZE
, "topic_heap");
68 member_heap
= rb_bh_create(sizeof(struct membership
), MEMBER_HEAP_SIZE
, "member_heap");
70 h_can_join
= register_hook("can_join");
71 h_can_send
= register_hook("can_send");
72 h_get_channel_access
= register_hook("get_channel_access");
76 * allocate_channel - Allocates a channel
79 allocate_channel(const char *chname
)
81 struct Channel
*chptr
;
82 chptr
= rb_bh_alloc(channel_heap
);
83 chptr
->chname
= rb_strdup(chname
);
88 free_channel(struct Channel
*chptr
)
90 rb_free(chptr
->chname
);
91 rb_free(chptr
->mode_lock
);
92 rb_bh_free(channel_heap
, chptr
);
96 allocate_ban(const char *banstr
, const char *who
, const char *forward
)
99 bptr
= rb_bh_alloc(ban_heap
);
100 bptr
->banstr
= rb_strdup(banstr
);
101 bptr
->who
= rb_strdup(who
);
102 bptr
->forward
= forward
? rb_strdup(forward
) : NULL
;
108 free_ban(struct Ban
*bptr
)
110 rb_free(bptr
->banstr
);
112 rb_free(bptr
->forward
);
113 rb_bh_free(ban_heap
, bptr
);
117 * send_channel_join()
119 * input - channel to join, client joining.
121 * side effects - none
124 send_channel_join(struct Channel
*chptr
, struct Client
*client_p
)
126 if (!IsClient(client_p
))
129 sendto_channel_local_with_capability(client_p
, ALL_MEMBERS
, NOCAPS
, CLICAP_EXTENDED_JOIN
, chptr
, ":%s!%s@%s JOIN %s",
130 client_p
->name
, client_p
->username
, client_p
->host
, chptr
->chname
);
132 sendto_channel_local_with_capability(client_p
, ALL_MEMBERS
, CLICAP_EXTENDED_JOIN
, NOCAPS
, chptr
, ":%s!%s@%s JOIN %s %s :%s",
133 client_p
->name
, client_p
->username
, client_p
->host
, chptr
->chname
,
134 EmptyString(client_p
->user
->suser
) ? "*" : client_p
->user
->suser
,
137 /* Send away message to away-notify enabled clients. */
138 if (client_p
->user
->away
)
139 sendto_channel_local_with_capability_butone(client_p
, ALL_MEMBERS
, CLICAP_AWAY_NOTIFY
, NOCAPS
, chptr
,
140 ":%s!%s@%s AWAY :%s", client_p
->name
, client_p
->username
,
141 client_p
->host
, client_p
->user
->away
);
144 /* find_channel_membership()
146 * input - channel to find them in, client to find
147 * output - membership of client in channel, else NULL
151 find_channel_membership(struct Channel
*chptr
, struct Client
*client_p
)
153 struct membership
*msptr
;
156 if(!IsClient(client_p
))
159 /* Pick the most efficient list to use to be nice to things like
160 * CHANSERV which could be in a large number of channels
162 if(rb_dlink_list_length(&chptr
->members
) < rb_dlink_list_length(&client_p
->user
->channel
))
164 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
168 if(msptr
->client_p
== client_p
)
174 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
178 if(msptr
->chptr
== chptr
)
186 /* find_channel_status()
188 * input - membership to get status for, whether we can combine flags
189 * output - flags of user on channel
193 find_channel_status(struct membership
*msptr
, int combine
)
195 static char buffer
[3];
214 /* add_user_to_channel()
216 * input - channel to add client to, client to add, channel flags
218 * side effects - user is added to channel
221 add_user_to_channel(struct Channel
*chptr
, struct Client
*client_p
, int flags
)
223 struct membership
*msptr
;
226 s_assert(client_p
->user
!= NULL
);
227 if(client_p
->user
== NULL
)
230 msptr
= rb_bh_alloc(member_heap
);
232 msptr
->chptr
= chptr
;
233 msptr
->client_p
= client_p
;
234 msptr
->flags
= flags
;
236 RB_DLINK_FOREACH(p
, client_p
->user
->channel
.head
)
238 struct membership
*ms2
= p
->data
;
239 if (irccmp(chptr
->chname
, ms2
->chptr
->chname
) < 0)
243 rb_dlinkAddTail(msptr
, &msptr
->usernode
, &client_p
->user
->channel
);
245 rb_dlinkAddBefore(p
, msptr
, &msptr
->usernode
, &client_p
->user
->channel
);
247 rb_dlinkAdd(msptr
, &msptr
->channode
, &chptr
->members
);
249 if(MyClient(client_p
))
250 rb_dlinkAdd(msptr
, &msptr
->locchannode
, &chptr
->locmembers
);
253 /* remove_user_from_channel()
255 * input - membership pointer to remove from channel
257 * side effects - membership (thus user) is removed from channel
260 remove_user_from_channel(struct membership
*msptr
)
262 struct Client
*client_p
;
263 struct Channel
*chptr
;
264 s_assert(msptr
!= NULL
);
268 client_p
= msptr
->client_p
;
269 chptr
= msptr
->chptr
;
271 rb_dlinkDelete(&msptr
->usernode
, &client_p
->user
->channel
);
272 rb_dlinkDelete(&msptr
->channode
, &chptr
->members
);
274 if(client_p
->servptr
== &me
)
275 rb_dlinkDelete(&msptr
->locchannode
, &chptr
->locmembers
);
277 if(!(chptr
->mode
.mode
& MODE_PERMANENT
) && rb_dlink_list_length(&chptr
->members
) <= 0)
278 destroy_channel(chptr
);
280 rb_bh_free(member_heap
, msptr
);
285 /* remove_user_from_channels()
287 * input - user to remove from all channels
289 * side effects - user is removed from all channels
292 remove_user_from_channels(struct Client
*client_p
)
294 struct Channel
*chptr
;
295 struct membership
*msptr
;
297 rb_dlink_node
*next_ptr
;
302 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, client_p
->user
->channel
.head
)
305 chptr
= msptr
->chptr
;
307 rb_dlinkDelete(&msptr
->channode
, &chptr
->members
);
309 if(client_p
->servptr
== &me
)
310 rb_dlinkDelete(&msptr
->locchannode
, &chptr
->locmembers
);
312 if(!(chptr
->mode
.mode
& MODE_PERMANENT
) && rb_dlink_list_length(&chptr
->members
) <= 0)
313 destroy_channel(chptr
);
315 rb_bh_free(member_heap
, msptr
);
318 client_p
->user
->channel
.head
= client_p
->user
->channel
.tail
= NULL
;
319 client_p
->user
->channel
.length
= 0;
322 /* invalidate_bancache_user()
324 * input - user to invalidate ban cache for
326 * side effects - ban cache is invalidated for all memberships of that user
327 * to be used after a nick change
330 invalidate_bancache_user(struct Client
*client_p
)
332 struct membership
*msptr
;
338 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
342 msptr
->flags
&= ~CHFL_BANNED
;
346 /* check_channel_name()
348 * input - channel name
349 * output - true if valid channel name, else false
353 check_channel_name(const char *name
)
355 s_assert(name
!= NULL
);
359 for (; *name
; ++name
)
361 if(!IsChanChar(*name
))
368 /* free_channel_list()
370 * input - rb_dlink list to free
372 * side effects - list of b/e/I modes is cleared
375 free_channel_list(rb_dlink_list
* list
)
378 rb_dlink_node
*next_ptr
;
379 struct Ban
*actualBan
;
381 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, list
->head
)
383 actualBan
= ptr
->data
;
387 list
->head
= list
->tail
= NULL
;
393 * input - channel to destroy
395 * side effects - channel is obliterated
398 destroy_channel(struct Channel
*chptr
)
400 rb_dlink_node
*ptr
, *next_ptr
;
402 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->invites
.head
)
404 del_invite(chptr
, ptr
->data
);
407 /* free all bans/exceptions/denies */
408 free_channel_list(&chptr
->banlist
);
409 free_channel_list(&chptr
->exceptlist
);
410 free_channel_list(&chptr
->invexlist
);
411 free_channel_list(&chptr
->quietlist
);
416 rb_dlinkDelete(&chptr
->node
, &global_channel_list
);
417 del_from_channel_hash(chptr
->chname
, chptr
);
421 /* channel_pub_or_secret()
424 * output - "=" if public, "@" if secret, else "*"
428 channel_pub_or_secret(struct Channel
*chptr
)
430 if(PubChannel(chptr
))
432 else if(SecretChannel(chptr
))
438 iter_comm_channels_step(rb_dlink_node
*pos1
, rb_dlink_node
*pos2
,
439 struct membership
**ms1
, struct membership
**ms2
,
440 struct Channel
**chptr
)
442 *ms1
= pos1
? pos1
->data
: NULL
;
443 *ms2
= pos2
? pos2
->data
: NULL
;
445 /* we're at the end */
446 if (*ms1
== NULL
&& *ms2
== NULL
)
449 /* one side is at the end, keep stepping the other one */
450 if (*ms1
== NULL
|| *ms2
== NULL
)
452 *chptr
= *ms1
!= NULL
? (*ms1
)->chptr
: (*ms2
)->chptr
;
457 if ((*ms1
)->chptr
== (*ms2
)->chptr
)
459 *chptr
= (*ms1
)->chptr
;
463 /* null out the channel that's further ahead; we'll get to it later */
464 if (irccmp((*ms1
)->chptr
->chname
, (*ms2
)->chptr
->chname
) > 0)
467 *chptr
= (*ms2
)->chptr
;
473 *chptr
= (*ms1
)->chptr
;
478 /* channel_member_names()
480 * input - channel to list, client to list to, show endofnames
482 * side effects - client is given list of users on channel
485 channel_member_names(struct Channel
*chptr
, struct Client
*client_p
, int show_eon
)
487 struct membership
*msptr
;
488 struct Client
*target_p
;
491 int stack
= IsCapable(client_p
, CLICAP_MULTI_PREFIX
);
493 if(ShowChannel(client_p
, chptr
))
495 is_member
= IsMember(client_p
, chptr
);
497 send_multiline_init(client_p
, " ", form_str(RPL_NAMREPLY
),
500 channel_pub_or_secret(chptr
),
503 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
506 target_p
= msptr
->client_p
;
508 if(IsInvisible(target_p
) && !is_member
)
511 if (IsCapable(client_p
, CLICAP_USERHOST_IN_NAMES
))
513 send_multiline_item(client_p
, "%s%s!%s@%s",
514 find_channel_status(msptr
, stack
),
521 send_multiline_item(client_p
, "%s%s",
522 find_channel_status(msptr
, stack
),
527 send_multiline_fini(client_p
, NULL
);
531 sendto_one(client_p
, form_str(RPL_ENDOFNAMES
),
532 me
.name
, client_p
->name
, chptr
->chname
);
537 * input - channel to remove invite from, client to remove
539 * side effects - user is removed from invite list, if exists
542 del_invite(struct Channel
*chptr
, struct Client
*who
)
544 rb_dlinkFindDestroy(who
, &chptr
->invites
);
545 rb_dlinkFindDestroy(chptr
, &who
->user
->invited
);
550 * input - channel to check bans for, ban list (banlist or quietlist),
551 * user to check bans against, optional prebuilt buffers,
552 * optional forward channel pointer
553 * output - 1 if banned, else 0
557 is_banned_list(struct Channel
*chptr
, rb_dlink_list
*list
,
558 struct Client
*who
, struct membership
*msptr
,
559 const struct matchset
*ms
, const char **forward
)
563 struct Ban
*actualBan
= NULL
;
564 struct Ban
*actualExcept
= NULL
;
571 matchset_for_client(who
, &ms_
);
575 RB_DLINK_FOREACH(ptr
, list
->head
)
577 actualBan
= ptr
->data
;
578 if (matches_mask(ms
, actualBan
->banstr
))
580 if (match_extban(actualBan
->banstr
, who
, chptr
, CHFL_BAN
))
585 if ((actualBan
!= NULL
) && ConfigChannel
.use_except
)
587 RB_DLINK_FOREACH(ptr
, chptr
->exceptlist
.head
)
589 actualExcept
= ptr
->data
;
591 /* theyre exempted.. */
592 if (matches_mask(ms
, actualExcept
->banstr
) ||
593 match_extban(actualExcept
->banstr
, who
, chptr
, CHFL_EXCEPTION
))
595 /* cache the fact theyre not banned */
598 msptr
->bants
= chptr
->bants
;
599 msptr
->flags
&= ~CHFL_BANNED
;
602 return CHFL_EXCEPTION
;
607 /* cache the banned/not banned status */
610 msptr
->bants
= chptr
->bants
;
612 if(actualBan
!= NULL
)
614 msptr
->flags
|= CHFL_BANNED
;
619 msptr
->flags
&= ~CHFL_BANNED
;
624 if (actualBan
&& actualBan
->forward
&& forward
)
625 *forward
= actualBan
->forward
;
627 return ((actualBan
? CHFL_BAN
: 0));
632 * input - channel to check bans for, user to check bans against
633 * optional prebuilt buffers, optional forward channel pointer
634 * output - 1 if banned, else 0
638 is_banned(struct Channel
*chptr
, struct Client
*who
, struct membership
*msptr
,
639 const struct matchset
*ms
, const char **forward
)
642 if (chptr
->last_checked_client
!= NULL
&&
643 who
== chptr
->last_checked_client
&&
644 chptr
->last_checked_type
== CHFL_BAN
&&
645 chptr
->last_checked_ts
> chptr
->bants
)
646 return chptr
->last_checked_result
;
648 chptr
->last_checked_client
= who
;
649 chptr
->last_checked_type
= CHFL_BAN
;
650 chptr
->last_checked_result
= is_banned_list(chptr
, &chptr
->banlist
, who
, msptr
, s
, s2
, forward
);
651 chptr
->last_checked_ts
= rb_current_time();
653 return chptr
->last_checked_result
;
655 return is_banned_list(chptr
, &chptr
->banlist
, who
, msptr
, ms
, forward
);
661 * input - channel to check bans for, user to check bans against
662 * optional prebuilt buffers
663 * output - 1 if banned, else 0
667 is_quieted(struct Channel
*chptr
, struct Client
*who
, struct membership
*msptr
,
668 const struct matchset
*ms
)
671 if (chptr
->last_checked_client
!= NULL
&&
672 who
== chptr
->last_checked_client
&&
673 chptr
->last_checked_type
== CHFL_QUIET
&&
674 chptr
->last_checked_ts
> chptr
->bants
)
675 return chptr
->last_checked_result
;
677 chptr
->last_checked_client
= who
;
678 chptr
->last_checked_type
= CHFL_QUIET
;
679 chptr
->last_checked_result
= is_banned_list(chptr
, &chptr
->quietlist
, who
, msptr
, s
, s2
, NULL
);
680 chptr
->last_checked_ts
= rb_current_time();
682 return chptr
->last_checked_result
;
684 return is_banned_list(chptr
, &chptr
->quietlist
, who
, msptr
, ms
, NULL
);
690 * input - client to check, channel to check for, key
691 * output - reason for not being able to join, else 0, channel name to forward to
693 * caveats - this function should only be called on a local user.
696 can_join(struct Client
*source_p
, struct Channel
*chptr
, const char *key
, const char **forward
)
698 rb_dlink_node
*invite
= NULL
;
700 struct Ban
*invex
= NULL
;
703 hook_data_channel moduledata
;
705 s_assert(source_p
->localClient
!= NULL
);
707 moduledata
.client
= source_p
;
708 moduledata
.chptr
= chptr
;
709 moduledata
.approved
= 0;
711 matchset_for_client(source_p
, &ms
);
713 if((is_banned(chptr
, source_p
, NULL
, &ms
, forward
)) == CHFL_BAN
)
715 moduledata
.approved
= ERR_BANNEDFROMCHAN
;
716 goto finish_join_check
;
719 if(*chptr
->mode
.key
&& (EmptyString(key
) || irccmp(chptr
->mode
.key
, key
)))
721 moduledata
.approved
= ERR_BADCHANNELKEY
;
722 goto finish_join_check
;
725 /* All checks from this point on will forward... */
727 *forward
= chptr
->mode
.forward
;
729 if(chptr
->mode
.mode
& MODE_INVITEONLY
)
731 RB_DLINK_FOREACH(invite
, source_p
->user
->invited
.head
)
733 if(invite
->data
== chptr
)
738 if(!ConfigChannel
.use_invex
)
739 moduledata
.approved
= ERR_INVITEONLYCHAN
;
740 RB_DLINK_FOREACH(ptr
, chptr
->invexlist
.head
)
743 if (matches_mask(&ms
, invex
->banstr
) ||
744 match_extban(invex
->banstr
, source_p
, chptr
, CHFL_INVEX
))
748 moduledata
.approved
= ERR_INVITEONLYCHAN
;
752 if(chptr
->mode
.limit
&&
753 rb_dlink_list_length(&chptr
->members
) >= (unsigned long) chptr
->mode
.limit
)
754 i
= ERR_CHANNELISFULL
;
755 if(chptr
->mode
.mode
& MODE_REGONLY
&& EmptyString(source_p
->user
->suser
))
756 i
= ERR_NEEDREGGEDNICK
;
757 /* join throttling stuff --nenolod */
758 else if(chptr
->mode
.join_num
> 0 && chptr
->mode
.join_time
> 0)
760 if ((rb_current_time() - chptr
->join_delta
<=
761 chptr
->mode
.join_time
) && (chptr
->join_count
>=
762 chptr
->mode
.join_num
))
766 /* allow /invite to override +l/+r/+j also -- jilles */
767 if (i
!= 0 && invite
== NULL
)
769 RB_DLINK_FOREACH(invite
, source_p
->user
->invited
.head
)
771 if(invite
->data
== chptr
)
775 moduledata
.approved
= i
;
779 call_hook(h_can_join
, &moduledata
);
781 return moduledata
.approved
;
786 * input - user to check in channel, membership pointer
787 * output - whether can explicitly send or not, else CAN_SEND_NONOP
791 can_send(struct Channel
*chptr
, struct Client
*source_p
, struct membership
*msptr
)
793 hook_data_channel_approval moduledata
;
795 moduledata
.approved
= CAN_SEND_NONOP
;
796 moduledata
.dir
= MODE_QUERY
;
798 if(IsServer(source_p
) || IsService(source_p
))
801 if(MyClient(source_p
) && hash_find_resv(chptr
->chname
) &&
802 !IsOper(source_p
) && !IsExemptResv(source_p
))
803 moduledata
.approved
= CAN_SEND_NO
;
807 msptr
= find_channel_membership(chptr
, source_p
);
811 /* if its +m or +n and theyre not in the channel,
812 * they cant send. we dont check bans here because
813 * theres no possibility of caching them --fl
815 if(chptr
->mode
.mode
& MODE_NOPRIVMSGS
|| chptr
->mode
.mode
& MODE_MODERATED
)
816 moduledata
.approved
= CAN_SEND_NO
;
818 moduledata
.approved
= CAN_SEND_NONOP
;
820 return moduledata
.approved
;
824 if(chptr
->mode
.mode
& MODE_MODERATED
)
825 moduledata
.approved
= CAN_SEND_NO
;
827 if(MyClient(source_p
))
829 /* cached can_send */
830 if(msptr
->bants
== chptr
->bants
)
832 if(can_send_banned(msptr
))
833 moduledata
.approved
= CAN_SEND_NO
;
835 else if(is_banned(chptr
, source_p
, msptr
, NULL
, NULL
) == CHFL_BAN
836 || is_quieted(chptr
, source_p
, msptr
, NULL
) == CHFL_BAN
)
837 moduledata
.approved
= CAN_SEND_NO
;
840 if(is_chanop_voiced(msptr
))
841 moduledata
.approved
= CAN_SEND_OPV
;
843 moduledata
.client
= source_p
;
844 moduledata
.chptr
= msptr
->chptr
;
845 moduledata
.msptr
= msptr
;
846 moduledata
.target
= NULL
;
847 moduledata
.dir
= (moduledata
.approved
== CAN_SEND_NO
) ? MODE_ADD
: MODE_QUERY
;
849 call_hook(h_can_send
, &moduledata
);
851 return moduledata
.approved
;
855 * flood_attack_channel
856 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
857 * says NOTICE must not auto reply
858 * - pointer to source Client
859 * - pointer to target channel
860 * output - true if target is under flood attack
861 * side effects - check for flood attack on target chptr
864 flood_attack_channel(enum message_type msgtype
, struct Client
*source_p
, struct Channel
*chptr
, char *chname
)
868 if(GlobalSetOptions
.floodcount
&& MyClient(source_p
))
870 if((chptr
->first_received_message_time
+ 1) < rb_current_time())
872 delta
= rb_current_time() - chptr
->first_received_message_time
;
873 chptr
->received_number_of_privmsgs
-= delta
;
874 chptr
->first_received_message_time
= rb_current_time();
875 if(chptr
->received_number_of_privmsgs
<= 0)
877 chptr
->received_number_of_privmsgs
= 0;
878 chptr
->flood_noticed
= 0;
882 if((chptr
->received_number_of_privmsgs
>= GlobalSetOptions
.floodcount
)
883 || chptr
->flood_noticed
)
885 if(chptr
->flood_noticed
== 0)
887 sendto_realops_snomask(SNO_BOTS
, *chptr
->chname
== '&' ? L_ALL
: L_NETWIDE
,
888 "Possible Flooder %s[%s@%s] on %s target: %s",
889 source_p
->name
, source_p
->username
,
891 source_p
->servptr
->name
, chptr
->chname
);
892 chptr
->flood_noticed
= 1;
894 /* Add a bit of penalty */
895 chptr
->received_number_of_privmsgs
+= 2;
897 if(MyClient(source_p
) && (msgtype
!= MESSAGE_TYPE_NOTICE
))
899 ":%s NOTICE %s :*** Message to %s throttled due to flooding",
900 me
.name
, source_p
->name
, chptr
->chname
);
904 chptr
->received_number_of_privmsgs
++;
910 /* find_bannickchange_channel()
911 * Input: client to check
912 * Output: channel preventing nick change
915 find_bannickchange_channel(struct Client
*client_p
)
917 struct Channel
*chptr
;
918 struct membership
*msptr
;
922 if (!MyClient(client_p
))
925 matchset_for_client(client_p
, &ms
);
927 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
930 chptr
= msptr
->chptr
;
931 if (is_chanop_voiced(msptr
))
933 /* cached can_send */
934 if (msptr
->bants
== chptr
->bants
)
936 if (can_send_banned(msptr
))
939 else if (is_banned(chptr
, client_p
, msptr
, &ms
, NULL
) == CHFL_BAN
940 || is_quieted(chptr
, client_p
, msptr
, &ms
) == CHFL_BAN
)
946 /* void check_spambot_warning(struct Client *source_p)
947 * Input: Client to check, channel name or NULL if this is a part.
949 * Side-effects: Updates the client's oper_warn_count_down, warns the
950 * IRC operators if necessary, and updates join_leave_countdown as
954 check_spambot_warning(struct Client
*source_p
, const char *name
)
958 if((GlobalSetOptions
.spam_num
&&
959 (source_p
->localClient
->join_leave_count
>= GlobalSetOptions
.spam_num
)))
961 if(source_p
->localClient
->oper_warn_count_down
> 0)
962 source_p
->localClient
->oper_warn_count_down
--;
964 source_p
->localClient
->oper_warn_count_down
= 0;
965 if(source_p
->localClient
->oper_warn_count_down
== 0 &&
968 /* Its already known as a possible spambot */
969 sendto_realops_snomask(SNO_BOTS
, L_NETWIDE
,
970 "User %s (%s@%s) trying to join %s is a possible spambot",
972 source_p
->username
, source_p
->orighost
, name
);
973 source_p
->localClient
->oper_warn_count_down
= OPER_SPAM_COUNTDOWN
;
979 (rb_current_time() - source_p
->localClient
->last_leave_time
)) >
980 JOIN_LEAVE_COUNT_EXPIRE_TIME
)
982 decrement_count
= (t_delta
/ JOIN_LEAVE_COUNT_EXPIRE_TIME
);
985 else if(decrement_count
> source_p
->localClient
->join_leave_count
)
986 source_p
->localClient
->join_leave_count
= 0;
988 source_p
->localClient
->join_leave_count
-= decrement_count
;
992 if((rb_current_time() -
993 (source_p
->localClient
->last_join_time
)) < GlobalSetOptions
.spam_time
)
995 /* oh, its a possible spambot */
996 source_p
->localClient
->join_leave_count
++;
1000 source_p
->localClient
->last_join_time
= rb_current_time();
1002 source_p
->localClient
->last_leave_time
= rb_current_time();
1006 /* check_splitmode()
1010 * side effects - compares usercount and servercount against their split
1011 * values and adjusts splitmode accordingly
1014 check_splitmode(void *unused
)
1016 if(splitchecking
&& (ConfigChannel
.no_join_on_split
|| ConfigChannel
.no_create_on_split
))
1018 /* not split, we're being asked to check now because someone
1023 if(eob_count
< split_servers
|| Count
.total
< split_users
)
1026 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1027 "Network split, activating splitmode");
1028 check_splitmode_ev
= rb_event_addish("check_splitmode", check_splitmode
, NULL
, 2);
1031 /* in splitmode, check whether its finished */
1032 else if(eob_count
>= split_servers
&& Count
.total
>= split_users
)
1036 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1037 "Network rejoined, deactivating splitmode");
1039 rb_event_delete(check_splitmode_ev
);
1040 check_splitmode_ev
= NULL
;
1048 * input - channel to allocate topic for
1049 * output - 1 on success, else 0
1050 * side effects - channel gets a topic allocated
1053 allocate_topic(struct Channel
*chptr
)
1060 ptr
= rb_bh_alloc(topic_heap
);
1062 /* Basically we allocate one large block for the topic and
1063 * the topic info. We then split it up into two and shove it
1067 chptr
->topic_info
= (char *) ptr
+ TOPICLEN
+ 1;
1068 *chptr
->topic
= '\0';
1069 *chptr
->topic_info
= '\0';
1074 * input - channel which has topic to free
1076 * side effects - channels topic is free'd
1079 free_topic(struct Channel
*chptr
)
1083 if(chptr
== NULL
|| chptr
->topic
== NULL
)
1086 /* This is safe for now - If you change allocate_topic you
1087 * MUST change this as well
1090 rb_bh_free(topic_heap
, ptr
);
1091 chptr
->topic
= NULL
;
1092 chptr
->topic_info
= NULL
;
1095 /* set_channel_topic()
1097 * input - channel, topic to set, topic info and topic ts
1099 * side effects - channels topic, topic info and TS are set.
1102 set_channel_topic(struct Channel
*chptr
, const char *topic
, const char *topic_info
, time_t topicts
)
1104 if(strlen(topic
) > 0)
1106 if(chptr
->topic
== NULL
)
1107 allocate_topic(chptr
);
1108 rb_strlcpy(chptr
->topic
, topic
, TOPICLEN
+ 1);
1109 rb_strlcpy(chptr
->topic_info
, topic_info
, USERHOST_REPLYLEN
);
1110 chptr
->topic_time
= topicts
;
1114 if(chptr
->topic
!= NULL
)
1116 chptr
->topic_time
= 0;
1122 * inputs - pointer to channel
1123 * - pointer to client
1124 * output - string with simple modes
1125 * side effects - result from previous calls overwritten
1127 * Stolen from ShadowIRCd 4 --nenolod
1130 channel_modes(struct Channel
*chptr
, struct Client
*client_p
)
1135 static char final
[BUFSIZE
];
1142 for (i
= 0; i
< 256; i
++)
1144 if(chmode_table
[i
].set_func
== chm_hidden
&& !HasPrivilege(client_p
, "auspex:cmodes") && IsClient(client_p
))
1146 if(chptr
->mode
.mode
& chmode_flags
[i
])
1150 if(chptr
->mode
.limit
)
1154 if(!IsClient(client_p
) || IsMember(client_p
, chptr
))
1155 pbuf
+= sprintf(pbuf
, " %d", chptr
->mode
.limit
);
1158 if(*chptr
->mode
.key
)
1162 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1163 pbuf
+= sprintf(pbuf
, " %s", chptr
->mode
.key
);
1166 if(chptr
->mode
.join_num
)
1170 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1171 pbuf
+= sprintf(pbuf
, " %d:%d", chptr
->mode
.join_num
,
1172 chptr
->mode
.join_time
);
1175 if(*chptr
->mode
.forward
&&
1176 (ConfigChannel
.use_forward
|| !IsClient(client_p
)))
1180 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1181 pbuf
+= sprintf(pbuf
, " %s", chptr
->mode
.forward
);
1186 rb_strlcpy(final
, buf1
, sizeof final
);
1187 rb_strlcat(final
, buf2
, sizeof final
);
1191 /* void send_cap_mode_changes(struct Client *client_p,
1192 * struct Client *source_p,
1193 * struct Channel *chptr, int cap, int nocap)
1194 * Input: The client sending(client_p), the source client(source_p),
1195 * the channel to send mode changes for(chptr)
1197 * Side-effects: Sends the appropriate mode changes to capable servers.
1199 * Reverted back to my original design, except that we now keep a count
1200 * of the number of servers which each combination as an optimisation, so
1201 * the capabs combinations which are not needed are not worked out. -A1kmm
1203 * Removed most code here because we don't need to be compatible with ircd
1204 * 2.8.21+CSr and stuff. --nenolod
1207 send_cap_mode_changes(struct Client
*client_p
, struct Client
*source_p
,
1208 struct Channel
*chptr
, struct ChModeChange mode_changes
[], int mode_count
)
1210 static char modebuf
[BUFSIZE
];
1211 static char parabuf
[BUFSIZE
];
1212 int i
, mbl
, pbl
, nc
, mc
, preflen
, len
;
1218 /* Now send to servers... */
1226 mbl
= preflen
= sprintf(modebuf
, ":%s TMODE %ld %s ",
1227 use_id(source_p
), (long) chptr
->channelts
,
1230 /* loop the list of - modes we have */
1231 for (i
= 0; i
< mode_count
; i
++)
1233 /* if they dont support the cap we need, or they do support a cap they
1234 * cant have, then dont add it to the modebuf.. that way they wont see
1237 if (mode_changes
[i
].letter
== 0)
1240 if (!EmptyString(mode_changes
[i
].id
))
1241 arg
= mode_changes
[i
].id
;
1243 arg
= mode_changes
[i
].arg
;
1247 arglen
= strlen(arg
);
1249 /* dont even think about it! --fl */
1250 if(arglen
> MODEBUFLEN
- 5)
1254 /* if we're creeping past the buf size, we need to send it and make
1255 * another line for the other modes
1256 * XXX - this could give away server topology with uids being
1257 * different lengths, but not much we can do, except possibly break
1258 * them as if they were the longest of the nick or uid at all times,
1259 * which even then won't work as we don't always know the uid -A1kmm.
1261 if(arg
&& ((mc
== MAXMODEPARAMSSERV
) ||
1262 ((mbl
+ pbl
+ arglen
+ 4) > (BUFSIZE
- 3))))
1265 sendto_server(client_p
, chptr
, NOCAPS
, NOCAPS
,
1266 "%s %s", modebuf
, parabuf
);
1277 if(dir
!= mode_changes
[i
].dir
)
1279 modebuf
[mbl
++] = (mode_changes
[i
].dir
== MODE_ADD
) ? '+' : '-';
1280 dir
= mode_changes
[i
].dir
;
1283 modebuf
[mbl
++] = mode_changes
[i
].letter
;
1289 len
= sprintf(pbuf
, "%s ", arg
);
1296 if(pbl
&& parabuf
[pbl
- 1] == ' ')
1297 parabuf
[pbl
- 1] = 0;
1300 sendto_server(client_p
, chptr
, NOCAPS
, NOCAPS
, "%s %s", modebuf
, parabuf
);
1304 resv_chan_forcepart(const char *name
, const char *reason
, int temp_time
)
1307 rb_dlink_node
*next_ptr
;
1308 struct Channel
*chptr
;
1309 struct membership
*msptr
;
1310 struct Client
*target_p
;
1312 if(!ConfigChannel
.resv_forcepart
)
1315 /* for each user on our server in the channel list
1316 * send them a PART, and notify opers.
1318 chptr
= find_channel(name
);
1321 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->locmembers
.head
)
1324 target_p
= msptr
->client_p
;
1326 if(IsExemptResv(target_p
))
1329 sendto_server(target_p
, chptr
, CAP_TS6
, NOCAPS
,
1330 ":%s PART %s", target_p
->id
, chptr
->chname
);
1332 sendto_channel_local(target_p
, ALL_MEMBERS
, chptr
, ":%s!%s@%s PART %s :%s",
1333 target_p
->name
, target_p
->username
,
1334 target_p
->host
, chptr
->chname
, target_p
->name
);
1336 remove_user_from_channel(msptr
);
1338 /* notify opers & user they were removed from the channel */
1339 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1340 "Forced PART for %s!%s@%s from %s (%s)",
1341 target_p
->name
, target_p
->username
,
1342 target_p
->host
, name
, reason
);
1345 sendto_one_notice(target_p
, ":*** Channel %s is temporarily unavailable on this server.",
1348 sendto_one_notice(target_p
, ":*** Channel %s is no longer available on this server.",