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
35 #include "s_newconf.h"
41 #include "ratelimit.h"
45 static const char join_desc
[] = "Provides the JOIN and TS6 SJOIN commands to facilitate joining and creating channels";
47 static void m_join(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
48 static void ms_join(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
49 static void ms_sjoin(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
51 static int h_can_create_channel
;
52 static int h_channel_join
;
53 static int h_channel_lowerts
;
55 struct Message join_msgtab
= {
57 {mg_unreg
, {m_join
, 2}, {ms_join
, 2}, mg_ignore
, mg_ignore
, {m_join
, 2}}
60 struct Message sjoin_msgtab
= {
62 {mg_unreg
, mg_ignore
, mg_ignore
, {ms_sjoin
, 4}, mg_ignore
, mg_ignore
}
65 mapi_clist_av1 join_clist
[] = { &join_msgtab
, &sjoin_msgtab
, NULL
};
67 mapi_hlist_av1 join_hlist
[] = {
68 { "can_create_channel", &h_can_create_channel
},
69 { "channel_join", &h_channel_join
},
70 { "channel_lowerts", &h_channel_lowerts
},
74 DECLARE_MODULE_AV2(join
, NULL
, NULL
, join_clist
, join_hlist
, NULL
, NULL
, NULL
, join_desc
);
76 static void do_join_0(struct Client
*client_p
, struct Client
*source_p
);
77 static bool check_channel_name_loc(struct Client
*source_p
, const char *name
);
78 static void send_join_error(struct Client
*source_p
, int numeric
, const char *name
);
80 static char *set_final_mode(char *mbuf
, char *parabuf
, struct Mode
*mode
, struct Mode
*oldmode
);
81 static void remove_our_modes(struct Channel
*chptr
, struct Client
*source_p
);
83 static void remove_ban_list(struct Channel
*chptr
, struct Client
*source_p
,
84 rb_dlink_list
* list
, char c
, int mems
);
86 /* Check what we will forward to, without sending any notices to the user
89 static struct Channel
*
90 check_forward(struct Client
*source_p
, struct Channel
*chptr
,
94 const char *next
= NULL
;
96 /* The caller (m_join) is only interested in the reason
97 * for the original channel.
99 if ((*err
= can_join(source_p
, chptr
, key
, &next
)) == 0)
102 /* User is +Q, or forwarding disabled */
103 if (IsNoForward(source_p
) || !ConfigChannel
.use_forward
)
111 chptr
= find_channel(next
);
112 /* Can only forward to existing channels */
115 /* Already on there... but don't send the original reason for
116 * being unable to join. It isn't their fault they're already
117 * on the channel, and it looks hostile otherwise.
120 if (IsMember(source_p
, chptr
))
122 *err
= ERR_USERONCHANNEL
; /* I'm borrowing this for now. --Elizafox */
125 /* Juped. Sending a warning notice would be unfair */
126 if (hash_find_resv(chptr
->chname
))
128 /* Don't forward to +Q channel */
129 if (chptr
->mode
.mode
& MODE_DISFORWARD
)
132 i
= can_join(source_p
, chptr
, key
, &next
);
144 * parv[2] = channel password (key)
147 m_join(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
149 static char jbuf
[BUFSIZE
];
150 struct Channel
*chptr
= NULL
, *chptr2
= NULL
;
151 struct ConfItem
*aconf
;
156 char *p
= NULL
, *p2
= NULL
;
162 /* rebuild the list of channels theyre supposed to be joining.
163 * this code has a side effect of losing keys, but..
165 chanlist
= LOCAL_COPY(parv
[1]);
166 for(name
= rb_strtok_r(chanlist
, ",", &p
); name
; name
= rb_strtok_r(NULL
, ",", &p
))
168 /* check the length and name of channel is ok */
169 if(!check_channel_name_loc(source_p
, name
) || (strlen(name
) > LOC_CHANNELLEN
))
171 sendto_one_numeric(source_p
, ERR_BADCHANNAME
,
172 form_str(ERR_BADCHANNAME
), (unsigned char *) name
);
176 /* join 0 parts all channels */
177 if(*name
== '0' && (name
[1] == ',' || name
[1] == '\0') && name
== chanlist
)
179 rb_strlcpy(jbuf
, "0", sizeof(jbuf
));
183 /* check it begins with a valid channel prefix per policy. */
184 else if (!IsChannelName(name
))
186 sendto_one_numeric(source_p
, ERR_NOSUCHCHANNEL
,
187 form_str(ERR_NOSUCHCHANNEL
), name
);
191 /* see if its resv'd */
192 if(!IsExemptResv(source_p
) && (aconf
= hash_find_resv(name
)))
194 sendto_one_numeric(source_p
, ERR_BADCHANNAME
,
195 form_str(ERR_BADCHANNAME
), name
);
197 /* dont warn for opers */
198 if(!IsExemptJupe(source_p
) && !IsOper(source_p
))
199 sendto_realops_snomask(SNO_SPY
, L_NETWIDE
,
200 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
201 source_p
->name
, source_p
->username
,
202 source_p
->orighost
, name
, aconf
->passwd
);
203 /* dont update tracking for jupe exempt users, these
204 * are likely to be spamtrap leaves
206 else if(IsExemptJupe(source_p
))
212 if(splitmode
&& !IsOperGeneral(source_p
) && (*name
!= '&') &&
213 ConfigChannel
.no_join_on_split
)
215 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
216 me
.name
, source_p
->name
, name
);
221 (void) strcat(jbuf
, ",");
222 (void) rb_strlcat(jbuf
, name
, sizeof(jbuf
));
227 mykey
= LOCAL_COPY(parv
[2]);
228 key
= rb_strtok_r(mykey
, ",", &p2
);
231 for(name
= rb_strtok_r(jbuf
, ",", &p
); name
;
232 key
= (key
) ? rb_strtok_r(NULL
, ",", &p2
) : NULL
, name
= rb_strtok_r(NULL
, ",", &p
))
234 hook_data_channel_activity hook_info
;
236 /* JOIN 0 simply parts all channels the user is in */
237 if(*name
== '0' && !atoi(name
))
239 if(source_p
->user
->channel
.head
== NULL
)
242 do_join_0(&me
, source_p
);
246 /* look for the channel */
247 if((chptr
= find_channel(name
)) != NULL
)
249 if(IsMember(source_p
, chptr
))
256 hook_data_client_approval moduledata
;
258 moduledata
.client
= source_p
;
259 moduledata
.approved
= 0;
261 call_hook(h_can_create_channel
, &moduledata
);
263 if(moduledata
.approved
!= 0)
265 if(moduledata
.approved
!= ERR_CUSTOM
)
266 send_join_error(source_p
,
272 if(splitmode
&& !IsOperGeneral(source_p
) && (*name
!= '&') &&
273 ConfigChannel
.no_create_on_split
)
275 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
276 me
.name
, source_p
->name
, name
);
283 if((rb_dlink_list_length(&source_p
->user
->channel
) >=
284 (unsigned long) ConfigChannel
.max_chans_per_user
) &&
285 (!IsExtendChans(source_p
) ||
286 (rb_dlink_list_length(&source_p
->user
->channel
) >=
287 (unsigned long) ConfigChannel
.max_chans_per_user_large
)))
289 sendto_one(source_p
, form_str(ERR_TOOMANYCHANNELS
),
290 me
.name
, source_p
->name
, name
);
294 if(chptr
== NULL
) /* If I already have a chptr, no point doing this */
296 chptr
= get_or_create_channel(source_p
, name
, NULL
);
300 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
301 me
.name
, source_p
->name
, name
);
306 /* If check_forward returns NULL, they couldn't join and there wasn't a usable forward channel. */
307 if((chptr2
= check_forward(source_p
, chptr
, key
, &i
)) == NULL
)
309 /* might be wrong, but is there any other better location for such?
310 * see extensions/chm_operonly.c for other comments on this
314 send_join_error(source_p
, i
, name
);
317 else if(chptr
!= chptr2
)
318 sendto_one_numeric(source_p
, ERR_LINKCHANNEL
, form_str(ERR_LINKCHANNEL
), name
, chptr2
->chname
);
323 !IsOperGeneral(source_p
) && !IsExemptSpambot(source_p
))
324 check_spambot_warning(source_p
, name
);
326 /* add the user to the channel */
327 add_user_to_channel(chptr
, source_p
, flags
);
328 if (chptr
->mode
.join_num
&&
329 rb_current_time() - chptr
->join_delta
>= chptr
->mode
.join_time
)
331 chptr
->join_count
= 0;
332 chptr
->join_delta
= rb_current_time();
336 /* credit user for join */
337 credit_client_join(source_p
);
339 /* we send the user their join here, because we could have to
340 * send a mode out next.
342 send_channel_join(chptr
, source_p
);
344 /* its a new channel, set +nt and burst. */
345 if(flags
& CHFL_CHANOP
)
347 chptr
->channelts
= rb_current_time();
348 chptr
->mode
.mode
|= ConfigChannel
.autochanmodes
;
349 modes
= channel_modes(chptr
, &me
);
351 sendto_channel_local(&me
, ONLY_CHANOPS
, chptr
, ":%s MODE %s %s",
352 me
.name
, chptr
->chname
, modes
);
354 sendto_server(client_p
, chptr
, CAP_TS6
, NOCAPS
,
355 ":%s SJOIN %ld %s %s :@%s",
356 me
.id
, (long) chptr
->channelts
,
357 chptr
->chname
, modes
, source_p
->id
);
361 sendto_server(client_p
, chptr
, CAP_TS6
, NOCAPS
,
363 use_id(source_p
), (long) chptr
->channelts
,
367 del_invite(chptr
, source_p
);
369 if(chptr
->topic
!= NULL
)
371 sendto_one(source_p
, form_str(RPL_TOPIC
), me
.name
,
372 source_p
->name
, chptr
->chname
, chptr
->topic
);
374 sendto_one(source_p
, form_str(RPL_TOPICWHOTIME
),
375 me
.name
, source_p
->name
, chptr
->chname
,
377 (unsigned long)chptr
->topic_time
);
380 channel_member_names(chptr
, source_p
, 1);
382 hook_info
.client
= source_p
;
383 hook_info
.chptr
= chptr
;
385 call_hook(h_channel_join
, &hook_info
);
391 * parv[1] = channel TS
393 * parv[3] = "+", formerly channel modes but now unused
394 * alternatively, a single "0" parameter parts all channels
397 ms_join(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
399 static char modebuf
[MODEBUFLEN
];
400 static char parabuf
[MODEBUFLEN
];
401 struct Channel
*chptr
;
402 static struct Mode mode
;
406 bool keep_our_modes
= true;
407 rb_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;
431 if((chptr
= get_or_create_channel(source_p
, parv
[2], &isnew
)) == NULL
)
434 newts
= atol(parv
[1]);
435 oldts
= chptr
->channelts
;
437 /* making a channel TS0 */
438 if(!isnew
&& !newts
&& oldts
)
440 sendto_channel_local(&me
, ALL_MEMBERS
, chptr
,
441 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to 0",
442 me
.name
, chptr
->chname
, chptr
->chname
, (long) oldts
);
443 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
444 "Server %s changing TS on %s from %ld to 0",
445 source_p
->name
, chptr
->chname
, (long) oldts
);
449 chptr
->channelts
= newts
;
450 else if(newts
== 0 || oldts
== 0)
451 chptr
->channelts
= 0;
452 else if(newts
== oldts
)
454 else if(newts
< oldts
)
456 keep_our_modes
= false;
457 chptr
->channelts
= newts
;
460 /* Lost the TS, other side wins, so remove modes on this side */
463 mbuf
= set_final_mode(mbuf
, parabuf
, &mode
, &chptr
->mode
);
465 remove_our_modes(chptr
, source_p
);
466 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->invites
.head
)
468 del_invite(chptr
, ptr
->data
);
470 /* If setting -j, clear join throttle state -- jilles */
471 chptr
->join_count
= chptr
->join_delta
= 0;
472 sendto_channel_local(&me
, ALL_MEMBERS
, chptr
,
473 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
474 me
.name
, chptr
->chname
, chptr
->chname
,
475 (long) oldts
, (long) newts
);
476 /* Update capitalization in channel name, this makes the
477 * capitalization timestamped like modes are -- jilles */
478 strcpy(chptr
->chname
, parv
[2]);
480 sendto_channel_local(source_p
->servptr
, ALL_MEMBERS
, chptr
,
482 source_p
->servptr
->name
,
483 chptr
->chname
, modebuf
, parabuf
);
484 *modebuf
= *parabuf
= '\0';
486 /* since we're dropping our modes, we want to clear the mlock as well. --nenolod */
487 set_channel_mlock(client_p
, source_p
, chptr
, NULL
, false);
489 hook_data_channel hookdata
;
490 hookdata
.client
= source_p
;
491 hookdata
.chptr
= chptr
;
493 call_hook(h_channel_lowerts
, &hookdata
);
496 if(!IsMember(source_p
, chptr
))
498 add_user_to_channel(chptr
, source_p
, CHFL_PEON
);
499 if (chptr
->mode
.join_num
&&
500 rb_current_time() - chptr
->join_delta
>= chptr
->mode
.join_time
)
502 chptr
->join_count
= 0;
503 chptr
->join_delta
= rb_current_time();
506 send_channel_join(chptr
, source_p
);
509 sendto_server(client_p
, chptr
, CAP_TS6
, NOCAPS
,
511 source_p
->id
, (long) chptr
->channelts
, chptr
->chname
);
515 ms_sjoin(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
517 static char modebuf
[MODEBUFLEN
];
518 static char parabuf
[MODEBUFLEN
];
519 static char buf_uid
[BUFSIZE
];
520 static const char empty_modes
[] = "0";
521 struct Channel
*chptr
;
522 struct Client
*target_p
, *fakesource_p
;
525 static struct Mode mode
, *oldmode
;
528 bool keep_our_modes
= true;
529 bool keep_new_modes
= true;
539 int i
, joinc
= 0, timeslice
= 0;
540 static char empty
[] = "";
541 rb_dlink_node
*ptr
, *next_ptr
;
544 const char *para
[MAXMODEPARAMS
];
549 if(!IsChannelName(parv
[2]) || !check_channel_name(parv
[2]))
552 /* SJOIN's for local channels can't happen. */
556 modebuf
[0] = parabuf
[0] = mode
.key
[0] = mode
.forward
[0] = '\0';
557 pargs
= mode
.mode
= mode
.limit
= mode
.join_num
= mode
.join_time
= 0;
559 /* Hide connecting server on netburst -- jilles */
560 if (ConfigServerHide
.flatten_links
&& !HasSentEob(source_p
))
563 fakesource_p
= source_p
;
566 newts
= atol(parv
[1]);
574 rb_strlcpy(mode
.forward
, parv
[4 + args
], sizeof(mode
.forward
));
580 sscanf(parv
[4 + args
], "%d:%d", &joinc
, ×lice
);
582 mode
.join_num
= joinc
;
583 mode
.join_time
= timeslice
;
588 rb_strlcpy(mode
.key
, parv
[4 + args
], sizeof(mode
.key
));
594 mode
.limit
= atoi(parv
[4 + args
]);
600 if(chmode_flags
[(int) *s
] != 0)
602 mode
.mode
|= chmode_flags
[(int) *s
];
611 /* remove any leading spaces */
618 if((chptr
= get_or_create_channel(source_p
, parv
[2], &isnew
)) == NULL
)
619 return; /* channel name too long? */
622 oldts
= chptr
->channelts
;
623 oldmode
= &chptr
->mode
;
625 if(!isnew
&& !newts
&& oldts
)
627 sendto_channel_local(&me
, ALL_MEMBERS
, chptr
,
628 ":%s NOTICE %s :*** Notice -- TS for %s "
629 "changed from %ld to 0",
630 me
.name
, chptr
->chname
, chptr
->chname
, (long) oldts
);
631 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
632 "Server %s changing TS on %s from %ld to 0",
633 source_p
->name
, chptr
->chname
, (long) oldts
);
637 chptr
->channelts
= newts
;
639 else if(newts
== 0 || oldts
== 0)
640 chptr
->channelts
= 0;
641 else if(newts
== oldts
)
643 else if(newts
< oldts
)
645 /* If configured, kick people trying to join +i/+k
646 * channels by recreating them on split servers.
647 * If the source has sent EOB, assume this is some
648 * sort of hack by services. If cmode +i is set,
649 * services can send kicks if needed; if the key
650 * differs, services cannot kick in a race-free
651 * manner so do so here.
653 if (ConfigChannel
.kick_on_split_riding
&&
654 ((!HasSentEob(source_p
) &&
655 mode
.mode
& MODE_INVITEONLY
) ||
656 (mode
.key
[0] != 0 && irccmp(mode
.key
, oldmode
->key
) != 0)))
658 struct membership
*msptr
;
660 int l
= rb_dlink_list_length(&chptr
->members
);
662 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->locmembers
.head
)
665 who
= msptr
->client_p
;
666 sendto_one(who
, ":%s KICK %s %s :Net Rider",
667 me
.name
, chptr
->chname
, who
->name
);
669 sendto_server(NULL
, chptr
, CAP_TS6
, NOCAPS
,
670 ":%s KICK %s %s :Net Rider",
671 me
.id
, chptr
->chname
,
673 remove_user_from_channel(msptr
);
679 /* Channel was emptied, create a new one */
680 if((chptr
= get_or_create_channel(source_p
, parv
[2], &isnew
)) == NULL
)
683 oldmode
= &chptr
->mode
;
686 keep_our_modes
= false;
687 chptr
->channelts
= newts
;
690 keep_new_modes
= false;
694 else if(keep_our_modes
)
696 mode
.mode
|= oldmode
->mode
;
697 if(oldmode
->limit
> mode
.limit
)
698 mode
.limit
= oldmode
->limit
;
699 if(strcmp(mode
.key
, oldmode
->key
) < 0)
700 rb_strlcpy(mode
.key
, oldmode
->key
, sizeof(mode
.key
));
701 if(oldmode
->join_num
> mode
.join_num
||
702 (oldmode
->join_num
== mode
.join_num
&&
703 oldmode
->join_time
> mode
.join_time
))
705 mode
.join_num
= oldmode
->join_num
;
706 mode
.join_time
= oldmode
->join_time
;
708 if(irccmp(mode
.forward
, oldmode
->forward
) < 0)
709 rb_strlcpy(mode
.forward
, oldmode
->forward
, sizeof(mode
.forward
));
713 /* If setting -j, clear join throttle state -- jilles */
715 chptr
->join_count
= chptr
->join_delta
= 0;
718 mbuf
= set_final_mode(mbuf
, parabuf
, &mode
, oldmode
);
721 /* Lost the TS, other side wins, so remove modes on this side */
724 remove_our_modes(chptr
, fakesource_p
);
725 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->invites
.head
)
727 del_invite(chptr
, ptr
->data
);
730 if(rb_dlink_list_length(&chptr
->banlist
) > 0)
731 remove_ban_list(chptr
, fakesource_p
, &chptr
->banlist
, 'b', ALL_MEMBERS
);
732 if(rb_dlink_list_length(&chptr
->exceptlist
) > 0)
733 remove_ban_list(chptr
, fakesource_p
, &chptr
->exceptlist
,
735 if(rb_dlink_list_length(&chptr
->invexlist
) > 0)
736 remove_ban_list(chptr
, fakesource_p
, &chptr
->invexlist
,
738 if(rb_dlink_list_length(&chptr
->quietlist
) > 0)
739 remove_ban_list(chptr
, fakesource_p
, &chptr
->quietlist
,
743 sendto_channel_local(&me
, ALL_MEMBERS
, chptr
,
744 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
745 me
.name
, chptr
->chname
, chptr
->chname
,
746 (long) oldts
, (long) newts
);
747 /* Update capitalization in channel name, this makes the
748 * capitalization timestamped like modes are -- jilles */
749 strcpy(chptr
->chname
, parv
[2]);
751 /* since we're dropping our modes, we want to clear the mlock as well. --nenolod */
752 set_channel_mlock(client_p
, source_p
, chptr
, NULL
, false);
756 sendto_channel_local(fakesource_p
, ALL_MEMBERS
, chptr
, ":%s MODE %s %s %s",
757 fakesource_p
->name
, chptr
->chname
, modebuf
, parabuf
);
759 *modebuf
= *parabuf
= '\0';
761 if(parv
[3][0] != '0' && keep_new_modes
)
762 modes
= channel_modes(chptr
, source_p
);
766 mlen_uid
= sprintf(buf_uid
, ":%s SJOIN %ld %s %s :",
767 use_id(source_p
), (long) chptr
->channelts
, parv
[2], modes
);
768 ptr_uid
= buf_uid
+ mlen_uid
;
771 para
[0] = para
[1] = para
[2] = para
[3] = empty
;
775 /* if theres a space, theres going to be more than one nick, change the
776 * first space to \0, so s is just the first nick, and point p to the
779 if((p
= strchr(s
, ' ')) != NULL
)
790 for (i
= 0; i
< 2; i
++)
804 /* if the client doesnt exist or is fake direction, skip. */
805 if(!(target_p
= find_client(s
)) ||
806 (target_p
->from
!= client_p
) || !IsPerson(target_p
))
809 /* we assume for these we can fit at least one nick/uid in.. */
811 /* check we can fit another status+nick+space into a buffer */
812 if((mlen_uid
+ len_uid
+ IDLEN
+ 3) > (BUFSIZE
- 3))
814 *(ptr_uid
- 1) = '\0';
815 sendto_server(client_p
->from
, NULL
, CAP_TS6
, NOCAPS
, "%s", buf_uid
);
816 ptr_uid
= buf_uid
+ mlen_uid
;
834 /* copy the nick to the two buffers */
835 len
= sprintf(ptr_uid
, "%s ", use_id(target_p
));
842 if(!IsMember(target_p
, chptr
))
844 add_user_to_channel(chptr
, target_p
, fl
);
845 send_channel_join(chptr
, target_p
);
852 para
[pargs
++] = target_p
->name
;
854 /* a +ov user.. bleh */
857 /* its possible the +o has filled up MAXMODEPARAMS, if so, start
860 if(pargs
>= MAXMODEPARAMS
)
863 sendto_channel_local(fakesource_p
, ALL_MEMBERS
, chptr
,
864 ":%s MODE %s %s %s %s %s %s",
865 fakesource_p
->name
, chptr
->chname
,
867 para
[0], para
[1], para
[2], para
[3]);
870 para
[0] = para
[1] = para
[2] = para
[3] = NULL
;
875 para
[pargs
++] = target_p
->name
;
878 else if(fl
& CHFL_VOICE
)
881 para
[pargs
++] = target_p
->name
;
884 if(pargs
>= MAXMODEPARAMS
)
887 sendto_channel_local(fakesource_p
, ALL_MEMBERS
, chptr
,
888 ":%s MODE %s %s %s %s %s %s",
891 modebuf
, para
[0], para
[1], para
[2], para
[3]);
894 para
[0] = para
[1] = para
[2] = para
[3] = NULL
;
899 /* p points to the next nick */
902 /* if there was a trailing space and p was pointing to it, then we
903 * need to exit.. this has the side effect of breaking double spaces
904 * in an sjoin.. but that shouldnt happen anyway
906 if(s
&& (*s
== '\0'))
909 /* if p was NULL due to no spaces, s wont exist due to the above, so
910 * we cant check it for spaces.. if there are no spaces, then when
911 * we next get here, s will be NULL
913 if(s
&& ((p
= strchr(s
, ' ')) != NULL
))
922 sendto_channel_local(fakesource_p
, ALL_MEMBERS
, chptr
,
923 ":%s MODE %s %s %s %s %s %s",
924 fakesource_p
->name
, chptr
->chname
, modebuf
,
925 para
[0], CheckEmpty(para
[1]),
926 CheckEmpty(para
[2]), CheckEmpty(para
[3]));
929 if(!joins
&& !(chptr
->mode
.mode
& MODE_PERMANENT
) && isnew
)
931 destroy_channel(chptr
);
936 /* Keep the colon if we're sending an SJOIN without nicks -- jilles */
939 *(ptr_uid
- 1) = '\0';
942 sendto_server(client_p
->from
, NULL
, CAP_TS6
, NOCAPS
, "%s", buf_uid
);
948 * inputs - pointer to client doing join 0
950 * side effects - Use has decided to join 0. This is legacy
951 * from the days when channels were numbers not names. *sigh*
954 do_join_0(struct Client
*client_p
, struct Client
*source_p
)
956 struct membership
*msptr
;
957 struct Channel
*chptr
= NULL
;
960 /* Finish the flood grace period... */
961 if(MyClient(source_p
) && !IsFloodDone(source_p
))
962 flood_endgrace(source_p
);
964 sendto_server(client_p
, NULL
, CAP_TS6
, NOCAPS
, ":%s JOIN 0", use_id(source_p
));
966 while((ptr
= source_p
->user
->channel
.head
))
968 if(MyConnect(source_p
) &&
969 !IsOperGeneral(source_p
) && !IsExemptSpambot(source_p
))
970 check_spambot_warning(source_p
, NULL
);
973 chptr
= msptr
->chptr
;
974 sendto_channel_local(source_p
, ALL_MEMBERS
, chptr
, ":%s!%s@%s PART %s",
976 source_p
->username
, source_p
->host
, chptr
->chname
);
977 remove_user_from_channel(msptr
);
982 check_channel_name_loc(struct Client
*source_p
, const char *name
)
986 s_assert(name
!= NULL
);
987 if(EmptyString(name
))
990 if(ConfigFileEntry
.disable_fake_channels
&& !IsOperGeneral(source_p
))
992 for(p
= name
; *p
; ++p
)
994 if(!IsChanChar(*p
) || IsFakeChanChar(*p
))
1000 for(p
= name
; *p
; ++p
)
1007 if(ConfigChannel
.only_ascii_channels
)
1009 for(p
= name
; *p
; ++p
)
1010 if(*p
< 33 || *p
> 126)
1017 /* send_join_error()
1019 * input - client to send to, reason, channel name
1021 * side effects - error message sent to client
1024 send_join_error(struct Client
*source_p
, int numeric
, const char *name
)
1026 /* This stuff is necessary because the form_str macro only
1027 * accepts constants.
1031 #define NORMAL_NUMERIC(i) \
1033 sendto_one(source_p, form_str(i), \
1034 me.name, source_p->name, name); \
1037 NORMAL_NUMERIC(ERR_BANNEDFROMCHAN
);
1038 NORMAL_NUMERIC(ERR_INVITEONLYCHAN
);
1039 NORMAL_NUMERIC(ERR_BADCHANNELKEY
);
1040 NORMAL_NUMERIC(ERR_CHANNELISFULL
);
1041 NORMAL_NUMERIC(ERR_NEEDREGGEDNICK
);
1042 NORMAL_NUMERIC(ERR_THROTTLE
);
1045 sendto_one_numeric(source_p
, numeric
,
1046 "%s :Cannot join channel", name
);
1052 set_final_mode(char *mbuf
, char *parabuf
, struct Mode
*mode
, struct Mode
*oldmode
)
1054 int dir
= MODE_QUERY
;
1055 char *pbuf
= parabuf
;
1059 /* ok, first get a list of modes we need to add */
1060 for (i
= 0; i
< 256; i
++)
1062 if((mode
->mode
& chmode_flags
[i
]) && !(oldmode
->mode
& chmode_flags
[i
]))
1073 /* now the ones we need to remove. */
1074 for (i
= 0; i
< 256; i
++)
1076 if((oldmode
->mode
& chmode_flags
[i
]) && !(mode
->mode
& chmode_flags
[i
]))
1087 if(oldmode
->limit
&& !mode
->limit
)
1096 if(oldmode
->key
[0] && !mode
->key
[0])
1104 len
= sprintf(pbuf
, "%s ", oldmode
->key
);
1107 if(oldmode
->join_num
&& !mode
->join_num
)
1116 if(oldmode
->forward
[0] && !mode
->forward
[0])
1125 if(mode
->limit
&& oldmode
->limit
!= mode
->limit
)
1133 len
= sprintf(pbuf
, "%d ", mode
->limit
);
1136 if(mode
->key
[0] && strcmp(oldmode
->key
, mode
->key
))
1144 len
= sprintf(pbuf
, "%s ", mode
->key
);
1147 if(mode
->join_num
&& (oldmode
->join_num
!= mode
->join_num
|| oldmode
->join_time
!= mode
->join_time
))
1155 len
= sprintf(pbuf
, "%d:%d ", mode
->join_num
, mode
->join_time
);
1158 if(mode
->forward
[0] && strcmp(oldmode
->forward
, mode
->forward
) &&
1159 ConfigChannel
.use_forward
)
1167 len
= sprintf(pbuf
, "%s ", mode
->forward
);
1183 remove_our_modes(struct Channel
*chptr
, struct Client
*source_p
)
1185 struct membership
*msptr
;
1187 char lmodebuf
[MODEBUFLEN
];
1188 char *lpara
[MAXMODEPARAMS
];
1191 char *mbuf
= lmodebuf
;
1195 for(i
= 0; i
< MAXMODEPARAMS
; i
++)
1198 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
1202 if(is_chanop(msptr
))
1204 msptr
->flags
&= ~CHFL_CHANOP
;
1205 lpara
[count
++] = msptr
->client_p
->name
;
1208 /* +ov, might not fit so check. */
1209 if(is_voiced(msptr
))
1211 if(count
>= MAXMODEPARAMS
)
1214 sendto_channel_local(source_p
, ALL_MEMBERS
, chptr
,
1215 ":%s MODE %s %s %s %s %s %s",
1216 source_p
->name
, chptr
->chname
,
1217 lmodebuf
, lpara
[0], lpara
[1],
1218 lpara
[2], lpara
[3]);
1220 /* preserve the initial '-' */
1225 for(i
= 0; i
< MAXMODEPARAMS
; i
++)
1229 msptr
->flags
&= ~CHFL_VOICE
;
1230 lpara
[count
++] = msptr
->client_p
->name
;
1234 else if(is_voiced(msptr
))
1236 msptr
->flags
&= ~CHFL_VOICE
;
1237 lpara
[count
++] = msptr
->client_p
->name
;
1243 if(count
>= MAXMODEPARAMS
)
1246 sendto_channel_local(source_p
, ALL_MEMBERS
, chptr
,
1247 ":%s MODE %s %s %s %s %s %s",
1248 source_p
->name
, chptr
->chname
, lmodebuf
,
1249 lpara
[0], lpara
[1], lpara
[2], lpara
[3]);
1254 for(i
= 0; i
< MAXMODEPARAMS
; i
++)
1262 sendto_channel_local(source_p
, ALL_MEMBERS
, chptr
,
1263 ":%s MODE %s %s %s %s %s %s",
1264 source_p
->name
, chptr
->chname
, lmodebuf
,
1265 EmptyString(lpara
[0]) ? "" : lpara
[0],
1266 EmptyString(lpara
[1]) ? "" : lpara
[1],
1267 EmptyString(lpara
[2]) ? "" : lpara
[2],
1268 EmptyString(lpara
[3]) ? "" : lpara
[3]);
1273 /* remove_ban_list()
1275 * inputs - channel, source, list to remove, char of mode, caps needed
1277 * side effects - given list is removed, with modes issued to local clients
1280 remove_ban_list(struct Channel
*chptr
, struct Client
*source_p
,
1281 rb_dlink_list
* list
, char c
, int mems
)
1283 static char lmodebuf
[BUFSIZE
];
1284 static char lparabuf
[BUFSIZE
];
1287 rb_dlink_node
*next_ptr
;
1290 int cur_len
, mlen
, plen
;
1295 cur_len
= mlen
= sprintf(lmodebuf
, ":%s MODE %s -", source_p
->name
, chptr
->chname
);
1296 mbuf
= lmodebuf
+ mlen
;
1298 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, list
->head
)
1302 /* trailing space, and the mode letter itself */
1303 plen
= strlen(banptr
->banstr
) +
1304 (banptr
->forward
? strlen(banptr
->forward
) + 1 : 0) + 2;
1306 if(count
>= MAXMODEPARAMS
|| (cur_len
+ plen
) > BUFSIZE
- 4)
1308 /* remove trailing space */
1312 sendto_channel_local(source_p
, mems
, chptr
, "%s %s", lmodebuf
, lparabuf
);
1315 mbuf
= lmodebuf
+ mlen
;
1322 if (banptr
->forward
)
1323 pbuf
+= sprintf(pbuf
, "%s$%s ", banptr
->banstr
, banptr
->forward
);
1325 pbuf
+= sprintf(pbuf
, "%s ", banptr
->banstr
);
1333 sendto_channel_local(source_p
, mems
, chptr
, "%s %s", lmodebuf
, lparabuf
);
1335 list
->head
= list
->tail
= NULL
;