2 * ircd-ratbox: A slightly useful ircd.
3 * m_join.c: Joins a channel.
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: m_join.c 3173 2007-01-31 23:57:18Z jilles $
33 #include "irc_string.h"
39 #include "s_newconf.h"
43 #include "sprintf_irc.h"
46 static int m_join(struct Client
*, struct Client
*, int, const char **);
47 static int ms_join(struct Client
*, struct Client
*, int, const char **);
49 static int h_can_create_channel
;
50 static int h_channel_join
;
52 struct Message join_msgtab
= {
53 "JOIN", 0, 0, 0, MFLG_SLOW
,
54 {mg_unreg
, {m_join
, 2}, {ms_join
, 2}, mg_ignore
, mg_ignore
, {m_join
, 2}}
57 mapi_clist_av1 join_clist
[] = { &join_msgtab
, NULL
};
59 mapi_hlist_av1 join_hlist
[] = {
60 { "can_create_channel", &h_can_create_channel
},
61 { "channel_join", &h_channel_join
},
65 DECLARE_MODULE_AV1(join
, NULL
, NULL
, join_clist
, join_hlist
, NULL
, "$Revision: 3173 $");
67 static void do_join_0(struct Client
*client_p
, struct Client
*source_p
);
68 static int check_channel_name_loc(struct Client
*source_p
, const char *name
);
70 static void set_final_mode(struct Mode
*mode
, struct Mode
*oldmode
);
71 static void remove_our_modes(struct Channel
*chptr
, struct Client
*source_p
);
73 static char modebuf
[MODEBUFLEN
];
74 static char parabuf
[MODEBUFLEN
];
77 /* Check what we will forward to, without sending any notices to the user
80 static struct Channel
*
81 check_forward(struct Client
*source_p
, struct Channel
*chptr
,
87 if (IsNoForward(source_p
))
92 chptr
= find_channel(chptr
->mode
.forward
);
93 /* Can only forward to existing channels */
96 /* Already on there, show original error message */
97 if (IsMember(source_p
, chptr
))
99 /* Juped. Sending a warning notice would be unfair */
100 if (hash_find_resv(chptr
->chname
))
102 /* Don't forward to +Q channel */
103 if (chptr
->mode
.mode
& MODE_DISFORWARD
)
105 i
= can_join(source_p
, chptr
, key
);
108 if (i
!= ERR_INVITEONLYCHAN
&& i
!= ERR_NEEDREGGEDNICK
&& i
!= ERR_THROTTLE
&& i
!= ERR_CHANNELISFULL
)
118 * parv[0] = sender prefix
120 * parv[2] = channel password (key)
123 m_join(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
125 static char jbuf
[BUFSIZE
];
126 struct Channel
*chptr
= NULL
;
127 struct ConfItem
*aconf
;
131 char *p
= NULL
, *p2
= NULL
;
134 int successful_join_count
= 0; /* Number of channels successfully joined */
138 /* rebuild the list of channels theyre supposed to be joining.
139 * this code has a side effect of losing keys, but..
141 chanlist
= LOCAL_COPY(parv
[1]);
142 for(name
= strtoken(&p
, chanlist
, ","); name
; name
= strtoken(&p
, NULL
, ","))
144 /* check the length and name of channel is ok */
145 if(!check_channel_name_loc(source_p
, name
) || (strlen(name
) > LOC_CHANNELLEN
))
147 sendto_one_numeric(source_p
, ERR_BADCHANNAME
,
148 form_str(ERR_BADCHANNAME
), (unsigned char *) name
);
152 /* join 0 parts all channels */
153 if(*name
== '0' && !atoi(name
))
155 (void) strcpy(jbuf
, "0");
159 /* check it begins with # or &, and local chans are disabled */
160 else if(!IsChannelName(name
))
162 sendto_one_numeric(source_p
, ERR_NOSUCHCHANNEL
,
163 form_str(ERR_NOSUCHCHANNEL
), name
);
167 /* see if its resv'd */
168 if(!IsExemptResv(source_p
) && (aconf
= hash_find_resv(name
)))
170 sendto_one_numeric(source_p
, ERR_BADCHANNAME
,
171 form_str(ERR_BADCHANNAME
), name
);
173 /* dont warn for opers */
174 if(!IsExemptJupe(source_p
) && !IsOper(source_p
))
175 sendto_realops_snomask(SNO_SPY
, L_NETWIDE
,
176 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
177 source_p
->name
, source_p
->username
,
178 source_p
->orighost
, name
, aconf
->passwd
);
179 /* dont update tracking for jupe exempt users, these
180 * are likely to be spamtrap leaves
182 else if(IsExemptJupe(source_p
))
188 if(splitmode
&& !IsOper(source_p
) && (*name
!= '&') &&
189 ConfigChannel
.no_join_on_split
)
191 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
192 me
.name
, source_p
->name
, name
);
197 (void) strcat(jbuf
, ",");
198 (void) strlcat(jbuf
, name
, sizeof(jbuf
));
203 mykey
= LOCAL_COPY(parv
[2]);
204 key
= strtoken(&p2
, mykey
, ",");
207 for(name
= strtoken(&p
, jbuf
, ","); name
;
208 key
= (key
) ? strtoken(&p2
, NULL
, ",") : NULL
, name
= strtoken(&p
, NULL
, ","))
210 hook_data_channel_activity hook_info
;
212 /* JOIN 0 simply parts all channels the user is in */
213 if(*name
== '0' && !atoi(name
))
215 if(source_p
->user
->channel
.head
== NULL
)
218 do_join_0(&me
, source_p
);
222 /* look for the channel */
223 if((chptr
= find_channel(name
)) != NULL
)
225 if(IsMember(source_p
, chptr
))
232 hook_data_client_approval moduledata
;
234 moduledata
.client
= source_p
;
235 moduledata
.approved
= 0;
237 call_hook(h_can_create_channel
, &moduledata
);
239 if(moduledata
.approved
!= 0 && !IsOper(source_p
))
241 sendto_one(source_p
, form_str(moduledata
.approved
),
242 me
.name
, source_p
->name
, name
);
246 if(splitmode
&& !IsOper(source_p
) && (*name
!= '&') &&
247 ConfigChannel
.no_create_on_split
)
249 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
250 me
.name
, source_p
->name
, name
);
257 if((dlink_list_length(&source_p
->user
->channel
) >=
258 (unsigned long) ConfigChannel
.max_chans_per_user
) &&
259 (!IsOper(source_p
) ||
260 (dlink_list_length(&source_p
->user
->channel
) >=
261 (unsigned long) ConfigChannel
.max_chans_per_user
* 3)))
263 sendto_one(source_p
, form_str(ERR_TOOMANYCHANNELS
),
264 me
.name
, source_p
->name
, name
);
265 if(successful_join_count
)
266 source_p
->localClient
->last_join_time
= CurrentTime
;
270 if(flags
== 0) /* if channel doesn't exist, don't penalize */
271 successful_join_count
++;
273 if(chptr
== NULL
) /* If I already have a chptr, no point doing this */
275 chptr
= get_or_create_channel(source_p
, name
, NULL
);
279 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
280 me
.name
, source_p
->name
, name
);
281 if(successful_join_count
> 0)
282 successful_join_count
--;
287 if(!IsOper(source_p
) && !IsExemptSpambot(source_p
))
288 check_spambot_warning(source_p
, name
);
290 /* can_join checks for +i key, bans etc */
291 if((i
= can_join(source_p
, chptr
, key
)))
293 if ((i
!= ERR_NEEDREGGEDNICK
&& i
!= ERR_THROTTLE
&& i
!= ERR_INVITEONLYCHAN
&& i
!= ERR_CHANNELISFULL
) ||
294 (!ConfigChannel
.use_forward
|| (chptr
= check_forward(source_p
, chptr
, key
)) == NULL
))
296 sendto_one(source_p
, form_str(i
), me
.name
, source_p
->name
, name
);
297 if(successful_join_count
> 0)
298 successful_join_count
--;
301 sendto_one_numeric(source_p
, ERR_LINKCHANNEL
, form_str(ERR_LINKCHANNEL
), name
, chptr
->chname
);
304 /* add the user to the channel */
305 add_user_to_channel(chptr
, source_p
, flags
);
306 if (chptr
->mode
.join_num
&&
307 CurrentTime
- chptr
->join_delta
>= chptr
->mode
.join_time
)
309 chptr
->join_count
= 0;
310 chptr
->join_delta
= CurrentTime
;
314 /* we send the user their join here, because we could have to
315 * send a mode out next.
317 sendto_channel_local(ALL_MEMBERS
, chptr
, ":%s!%s@%s JOIN :%s",
319 source_p
->username
, source_p
->host
, chptr
->chname
);
321 /* its a new channel, set +nt and burst. */
322 if(flags
& CHFL_CHANOP
)
324 chptr
->channelts
= CurrentTime
;
325 chptr
->mode
.mode
|= MODE_TOPICLIMIT
;
326 chptr
->mode
.mode
|= MODE_NOPRIVMSGS
;
328 sendto_channel_local(ONLY_CHANOPS
, chptr
, ":%s MODE %s +nt",
329 me
.name
, chptr
->chname
);
331 if(*chptr
->chname
== '#')
333 sendto_server(client_p
, chptr
, CAP_TS6
, NOCAPS
,
334 ":%s SJOIN %ld %s +nt :@%s",
335 me
.id
, (long) chptr
->channelts
,
336 chptr
->chname
, source_p
->id
);
337 sendto_server(client_p
, chptr
, NOCAPS
, CAP_TS6
,
338 ":%s SJOIN %ld %s +nt :@%s",
339 me
.name
, (long) chptr
->channelts
,
340 chptr
->chname
, source_p
->name
);
345 const char *modes
= channel_modes(chptr
, &me
);
347 sendto_server(client_p
, chptr
, CAP_TS6
, NOCAPS
,
348 ":%s JOIN %ld %s %s",
349 use_id(source_p
), (long) chptr
->channelts
,
350 chptr
->chname
, modes
);
352 sendto_server(client_p
, chptr
, NOCAPS
, CAP_TS6
,
353 ":%s SJOIN %ld %s %s :%s",
354 me
.name
, (long) chptr
->channelts
,
355 chptr
->chname
, modes
, source_p
->name
);
358 del_invite(chptr
, source_p
);
360 if(chptr
->topic
!= NULL
)
362 sendto_one(source_p
, form_str(RPL_TOPIC
), me
.name
,
363 source_p
->name
, chptr
->chname
, chptr
->topic
);
365 sendto_one(source_p
, form_str(RPL_TOPICWHOTIME
),
366 me
.name
, source_p
->name
, chptr
->chname
,
367 chptr
->topic_info
, chptr
->topic_time
);
370 channel_member_names(chptr
, source_p
, 1);
372 if(successful_join_count
)
373 source_p
->localClient
->last_join_time
= CurrentTime
;
375 hook_info
.client
= source_p
;
376 hook_info
.chptr
= chptr
;
378 call_hook(h_channel_join
, &hook_info
);
389 * side effects - handles remote JOIN's sent by servers. In TSora
390 * remote clients are joined using SJOIN, hence a
391 * JOIN sent by a server on behalf of a client is an error.
392 * here, the initial code is in to take an extra parameter
393 * and use it for the TimeStamp on a new channel.
396 ms_join(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
398 struct Channel
*chptr
;
399 static struct Mode mode
, *oldmode
;
406 int keep_our_modes
= YES
;
407 int keep_new_modes
= YES
;
408 dlink_node
*ptr
, *next_ptr
;
410 /* special case for join 0 */
411 if((parv
[1][0] == '0') && (parv
[1][1] == '\0') && parc
== 2)
413 do_join_0(client_p
, source_p
);
420 if(!IsChannelName(parv
[2]) || !check_channel_name(parv
[2]))
423 /* joins for local channels cant happen. */
424 if(parv
[2][0] == '&')
428 mode
.key
[0] = mode
.forward
[0] = '\0';
429 mode
.mode
= mode
.limit
= mode
.join_num
= mode
.join_time
= 0;
437 mode
.mode
|= MODE_INVITEONLY
;
440 mode
.mode
|= MODE_NOPRIVMSGS
;
443 mode
.mode
|= MODE_PRIVATE
;
446 mode
.mode
|= MODE_SECRET
;
449 mode
.mode
|= MODE_MODERATED
;
452 mode
.mode
|= MODE_TOPICLIMIT
;
455 mode
.mode
|= MODE_REGONLY
;
458 mode
.mode
|= MODE_EXLIMIT
;
461 mode
.mode
|= MODE_PERMANENT
;
464 mode
.mode
|= MODE_NOCOLOR
;
467 mode
.mode
|= MODE_FREEINVITE
;
470 mode
.mode
|= MODE_OPMODERATE
;
473 mode
.mode
|= MODE_FREETARGET
;
476 mode
.mode
|= MODE_DISFORWARD
;
481 strlcpy(mode
.forward
, parv
[4 + args
], sizeof(mode
.forward
));
485 /* sent a +j without an arg. */
488 sscanf(parv
[4 + args
], "%d:%d", &mode
.join_num
, &mode
.join_time
);
492 /* sent a +k without a key, eek. */
495 strlcpy(mode
.key
, parv
[4 + args
], sizeof(mode
.key
));
499 /* sent a +l without a limit. */
502 mode
.limit
= atoi(parv
[4 + args
]);
508 if((chptr
= get_or_create_channel(source_p
, parv
[2], &isnew
)) == NULL
)
511 newts
= atol(parv
[1]);
512 oldts
= chptr
->channelts
;
513 oldmode
= &chptr
->mode
;
515 #ifdef IGNORE_BOGUS_TS
516 if(newts
< 800000000)
518 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
519 "*** Bogus TS %ld on %s ignored from %s",
520 (long) newts
, chptr
->chname
, client_p
->name
);
521 newts
= (oldts
== 0) ? oldts
: 800000000;
524 /* making a channel TS0 */
525 if(!isnew
&& !newts
&& oldts
)
527 sendto_channel_local(ALL_MEMBERS
, chptr
,
528 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to 0",
529 me
.name
, chptr
->chname
, chptr
->chname
, (long) oldts
);
530 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
531 "Server %s changing TS on %s from %ld to 0",
532 source_p
->name
, chptr
->chname
, (long) oldts
);
537 chptr
->channelts
= newts
;
538 else if(newts
== 0 || oldts
== 0)
539 chptr
->channelts
= 0;
540 else if(newts
== oldts
)
542 else if(newts
< oldts
)
545 chptr
->channelts
= newts
;
552 else if(keep_our_modes
)
554 mode
.mode
|= oldmode
->mode
;
555 if(oldmode
->limit
> mode
.limit
)
556 mode
.limit
= oldmode
->limit
;
557 if(strcmp(mode
.key
, oldmode
->key
) < 0)
558 strcpy(mode
.key
, oldmode
->key
);
559 if(oldmode
->join_num
> mode
.join_num
||
560 (oldmode
->join_num
== mode
.join_num
&&
561 oldmode
->join_time
> mode
.join_time
))
563 mode
.join_num
= oldmode
->join_num
;
564 mode
.join_time
= oldmode
->join_time
;
566 if(irccmp(mode
.forward
, oldmode
->forward
) < 0)
567 strcpy(mode
.forward
, oldmode
->forward
);
571 /* If setting -j, clear join throttle state -- jilles */
573 chptr
->join_count
= chptr
->join_delta
= 0;
576 set_final_mode(&mode
, oldmode
);
579 /* Lost the TS, other side wins, so remove modes on this side */
582 remove_our_modes(chptr
, source_p
);
583 DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->invites
.head
)
585 del_invite(chptr
, ptr
->data
);
587 sendto_channel_local(ALL_MEMBERS
, chptr
,
588 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
589 me
.name
, chptr
->chname
, chptr
->chname
,
590 (long) oldts
, (long) newts
);
594 sendto_channel_local(ALL_MEMBERS
, chptr
, ":%s MODE %s %s %s",
595 source_p
->user
->server
, chptr
->chname
, modebuf
, parabuf
);
597 *modebuf
= *parabuf
= '\0';
599 if(!IsMember(source_p
, chptr
))
601 add_user_to_channel(chptr
, source_p
, CHFL_PEON
);
602 if (chptr
->mode
.join_num
&&
603 CurrentTime
- chptr
->join_delta
>= chptr
->mode
.join_time
)
605 chptr
->join_count
= 0;
606 chptr
->join_delta
= CurrentTime
;
609 sendto_channel_local(ALL_MEMBERS
, chptr
, ":%s!%s@%s JOIN :%s",
610 source_p
->name
, source_p
->username
,
611 source_p
->host
, chptr
->chname
);
614 modes
= channel_modes(chptr
, client_p
);
615 sendto_server(client_p
, chptr
, CAP_TS6
, NOCAPS
,
616 ":%s JOIN %ld %s %s",
617 source_p
->id
, (long) chptr
->channelts
, chptr
->chname
, modes
);
618 sendto_server(client_p
, chptr
, NOCAPS
, CAP_TS6
,
619 ":%s SJOIN %ld %s %s :%s",
620 source_p
->user
->server
, (long) chptr
->channelts
,
621 chptr
->chname
, modes
, source_p
->name
);
628 * inputs - pointer to client doing join 0
630 * side effects - Use has decided to join 0. This is legacy
631 * from the days when channels were numbers not names. *sigh*
632 * There is a bunch of evilness necessary here due to
636 do_join_0(struct Client
*client_p
, struct Client
*source_p
)
638 struct membership
*msptr
;
639 struct Channel
*chptr
= NULL
;
642 /* Finish the flood grace period... */
643 if(MyClient(source_p
) && !IsFloodDone(source_p
))
644 flood_endgrace(source_p
);
647 sendto_server(client_p
, NULL
, NOCAPS
, NOCAPS
, ":%s JOIN 0", source_p
->name
);
649 if(source_p
->user
->channel
.head
&& MyConnect(source_p
) &&
650 !IsOper(source_p
) && !IsExemptSpambot(source_p
))
651 check_spambot_warning(source_p
, NULL
);
653 while((ptr
= source_p
->user
->channel
.head
))
656 chptr
= msptr
->chptr
;
657 sendto_channel_local(ALL_MEMBERS
, chptr
, ":%s!%s@%s PART %s",
659 source_p
->username
, source_p
->host
, chptr
->chname
);
660 remove_user_from_channel(msptr
);
665 check_channel_name_loc(struct Client
*source_p
, const char *name
)
667 s_assert(name
!= NULL
);
668 if(EmptyString(name
))
671 if(ConfigFileEntry
.disable_fake_channels
&& !IsOper(source_p
))
675 if(!IsChanChar(*name
) || IsFakeChanChar(*name
))
683 if(!IsChanChar(*name
))
697 static struct mode_letter flags
[] = {
698 {MODE_NOPRIVMSGS
, 'n'},
699 {MODE_TOPICLIMIT
, 't'},
701 {MODE_MODERATED
, 'm'},
702 {MODE_INVITEONLY
, 'i'},
706 {MODE_PERMANENT
, 'P'},
708 {MODE_FREEINVITE
, 'g'},
709 {MODE_OPMODERATE
, 'z'},
710 {MODE_FREETARGET
, 'F'},
711 {MODE_DISFORWARD
, 'Q'},
716 set_final_mode(struct Mode
*mode
, struct Mode
*oldmode
)
718 int dir
= MODE_QUERY
;
719 char *pbuf
= parabuf
;
723 /* ok, first get a list of modes we need to add */
724 for(i
= 0; flags
[i
].letter
; i
++)
726 if((mode
->mode
& flags
[i
].mode
) && !(oldmode
->mode
& flags
[i
].mode
))
733 *mbuf
++ = flags
[i
].letter
;
737 /* now the ones we need to remove. */
738 for(i
= 0; flags
[i
].letter
; i
++)
740 if((oldmode
->mode
& flags
[i
].mode
) && !(mode
->mode
& flags
[i
].mode
))
747 *mbuf
++ = flags
[i
].letter
;
751 if(oldmode
->limit
&& !mode
->limit
)
760 if(oldmode
->key
[0] && !mode
->key
[0])
768 len
= ircsprintf(pbuf
, "%s ", oldmode
->key
);
771 if(oldmode
->join_num
&& !mode
->join_num
)
780 if(oldmode
->forward
[0] && !mode
->forward
[0])
789 if(mode
->limit
&& oldmode
->limit
!= mode
->limit
)
797 len
= ircsprintf(pbuf
, "%d ", mode
->limit
);
800 if(mode
->key
[0] && strcmp(oldmode
->key
, mode
->key
))
808 len
= ircsprintf(pbuf
, "%s ", mode
->key
);
811 if(mode
->join_num
&& (oldmode
->join_num
!= mode
->join_num
|| oldmode
->join_time
!= mode
->join_time
))
819 len
= ircsprintf(pbuf
, "%d:%d ", mode
->join_num
, mode
->join_time
);
822 if(mode
->forward
[0] && strcmp(oldmode
->forward
, mode
->forward
) && ConfigChannel
.use_forward
)
830 len
= ircsprintf(pbuf
, "%s ", mode
->forward
);
844 remove_our_modes(struct Channel
*chptr
, struct Client
*source_p
)
846 struct membership
*msptr
;
848 char lmodebuf
[MODEBUFLEN
];
849 char *lpara
[MAXMODEPARAMS
];
856 for(i
= 0; i
< MAXMODEPARAMS
; i
++)
859 DLINK_FOREACH(ptr
, chptr
->members
.head
)
865 msptr
->flags
&= ~CHFL_CHANOP
;
866 lpara
[count
++] = msptr
->client_p
->name
;
869 /* +ov, might not fit so check. */
872 if(count
>= MAXMODEPARAMS
)
875 sendto_channel_local(ALL_MEMBERS
, chptr
,
876 ":%s MODE %s %s %s %s %s %s",
877 me
.name
, chptr
->chname
,
878 lmodebuf
, lpara
[0], lpara
[1],
881 /* preserve the initial '-' */
886 for(i
= 0; i
< MAXMODEPARAMS
; i
++)
890 msptr
->flags
&= ~CHFL_VOICE
;
891 lpara
[count
++] = msptr
->client_p
->name
;
895 else if(is_voiced(msptr
))
897 msptr
->flags
&= ~CHFL_VOICE
;
898 lpara
[count
++] = msptr
->client_p
->name
;
904 if(count
>= MAXMODEPARAMS
)
907 sendto_channel_local(ALL_MEMBERS
, chptr
,
908 ":%s MODE %s %s %s %s %s %s",
909 me
.name
, chptr
->chname
, lmodebuf
,
910 lpara
[0], lpara
[1], lpara
[2], lpara
[3]);
915 for(i
= 0; i
< MAXMODEPARAMS
; i
++)
923 sendto_channel_local(ALL_MEMBERS
, chptr
,
924 ":%s MODE %s %s %s %s %s %s",
925 me
.name
, chptr
->chname
, lmodebuf
,
926 EmptyString(lpara
[0]) ? "" : lpara
[0],
927 EmptyString(lpara
[1]) ? "" : lpara
[1],
928 EmptyString(lpara
[2]) ? "" : lpara
[2],
929 EmptyString(lpara
[3]) ? "" : lpara
[3]);