]> jfr.im git - solanum.git/blame - modules/core/m_join.c
Port ircd-seven banfowards to charybdis.
[solanum.git] / modules / core / m_join.c
CommitLineData
212380e3
AC
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_join.c: Joins a channel.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
f4a80ce6 24 * $Id: m_join.c 3494 2007-05-27 13:07:27Z jilles $
212380e3
AC
25 */
26
27#include "stdinc.h"
212380e3
AC
28#include "channel.h"
29#include "client.h"
30#include "common.h"
31#include "hash.h"
4562c604 32#include "match.h"
212380e3
AC
33#include "ircd.h"
34#include "numeric.h"
35#include "send.h"
36#include "s_serv.h"
37#include "s_conf.h"
38#include "s_newconf.h"
39#include "msg.h"
40#include "parse.h"
41#include "modules.h"
212380e3 42#include "packet.h"
acdf71d9 43#include "chmode.h"
212380e3
AC
44
45static int m_join(struct Client *, struct Client *, int, const char **);
46static int ms_join(struct Client *, struct Client *, int, const char **);
8cc12805 47static int ms_sjoin(struct Client *, struct Client *, int, const char **);
212380e3
AC
48
49static int h_can_create_channel;
50static int h_channel_join;
51
52struct 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}}
55};
56
8cc12805
VY
57struct Message sjoin_msgtab = {
58 "SJOIN", 0, 0, 0, MFLG_SLOW,
1766edef 59 {mg_unreg, mg_ignore, mg_ignore, {ms_sjoin, 4}, mg_ignore, mg_ignore}
8cc12805
VY
60};
61
62mapi_clist_av1 join_clist[] = { &join_msgtab, &sjoin_msgtab, NULL };
212380e3
AC
63
64mapi_hlist_av1 join_hlist[] = {
65 { "can_create_channel", &h_can_create_channel },
66 { "channel_join", &h_channel_join },
67 { NULL, NULL },
68};
69
f4a80ce6 70DECLARE_MODULE_AV1(join, NULL, NULL, join_clist, join_hlist, NULL, "$Revision: 3494 $");
212380e3 71
f4a80ce6 72static void do_join_0(struct Client *client_p, struct Client *source_p);
212380e3
AC
73static int check_channel_name_loc(struct Client *source_p, const char *name);
74
75static void set_final_mode(struct Mode *mode, struct Mode *oldmode);
76static void remove_our_modes(struct Channel *chptr, struct Client *source_p);
77
8cc12805 78static void remove_ban_list(struct Channel *chptr, struct Client *source_p,
8afeb720 79 rb_dlink_list * list, char c, int mems);
8cc12805 80
212380e3
AC
81static char modebuf[MODEBUFLEN];
82static char parabuf[MODEBUFLEN];
8cc12805 83static const char *para[MAXMODEPARAMS];
212380e3 84static char *mbuf;
8cc12805 85static int pargs;
212380e3
AC
86
87/* Check what we will forward to, without sending any notices to the user
88 * -- jilles
89 */
90static struct Channel *
91check_forward(struct Client *source_p, struct Channel *chptr,
765d839d 92 char *key, int *err)
212380e3
AC
93{
94 int depth = 0, i;
765d839d
EM
95 char *next = NULL;
96
97 /* The caller (m_join) is only interested in the reason
98 * for the original channel.
99 */
100 if ((*err = can_join(source_p, chptr, key, &next)) == 0)
101 return chptr;
212380e3
AC
102
103 /* User is +Q */
104 if (IsNoForward(source_p))
105 return NULL;
106
107 while (depth < 16)
108 {
765d839d 109 chptr = find_channel(next);
212380e3
AC
110 /* Can only forward to existing channels */
111 if (chptr == NULL)
112 return NULL;
113 /* Already on there, show original error message */
114 if (IsMember(source_p, chptr))
115 return NULL;
116 /* Juped. Sending a warning notice would be unfair */
117 if (hash_find_resv(chptr->chname))
118 return NULL;
119 /* Don't forward to +Q channel */
120 if (chptr->mode.mode & MODE_DISFORWARD)
121 return NULL;
765d839d 122 i = can_join(source_p, chptr, key, &next);
212380e3
AC
123 if (i == 0)
124 return chptr;
765d839d 125 if (next == NULL)
212380e3
AC
126 return NULL;
127 depth++;
128 }
129
130 return NULL;
131}
132
133/*
134 * m_join
212380e3
AC
135 * parv[1] = channel
136 * parv[2] = channel password (key)
137 */
138static int
139m_join(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
140{
141 static char jbuf[BUFSIZE];
765d839d 142 struct Channel *chptr = NULL, *chptr2 = NULL;
212380e3
AC
143 struct ConfItem *aconf;
144 char *name;
145 char *key = NULL;
095efcf0 146 const char *modes;
212380e3
AC
147 int i, flags = 0;
148 char *p = NULL, *p2 = NULL;
149 char *chanlist;
150 char *mykey;
212380e3
AC
151
152 jbuf[0] = '\0';
153
154 /* rebuild the list of channels theyre supposed to be joining.
155 * this code has a side effect of losing keys, but..
156 */
157 chanlist = LOCAL_COPY(parv[1]);
4a2651e5 158 for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
212380e3
AC
159 {
160 /* check the length and name of channel is ok */
161 if(!check_channel_name_loc(source_p, name) || (strlen(name) > LOC_CHANNELLEN))
162 {
163 sendto_one_numeric(source_p, ERR_BADCHANNAME,
164 form_str(ERR_BADCHANNAME), (unsigned char *) name);
165 continue;
166 }
167
f4a80ce6
JT
168 /* join 0 parts all channels */
169 if(*name == '0' && (name[1] == ',' || name[1] == '\0') && name == chanlist)
170 {
171 (void) strcpy(jbuf, "0");
172 continue;
173 }
174
212380e3 175 /* check it begins with # or &, and local chans are disabled */
341f971e
SB
176 else if(!IsChannelName(name) ||
177 ( ConfigChannel.disable_local_channels && name[0] == '&'))
212380e3
AC
178 {
179 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
180 form_str(ERR_NOSUCHCHANNEL), name);
181 continue;
182 }
183
184 /* see if its resv'd */
185 if(!IsExemptResv(source_p) && (aconf = hash_find_resv(name)))
186 {
187 sendto_one_numeric(source_p, ERR_BADCHANNAME,
188 form_str(ERR_BADCHANNAME), name);
189
190 /* dont warn for opers */
191 if(!IsExemptJupe(source_p) && !IsOper(source_p))
192 sendto_realops_snomask(SNO_SPY, L_NETWIDE,
193 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
194 source_p->name, source_p->username,
63aecfb9 195 source_p->orighost, name, aconf->passwd);
212380e3
AC
196 /* dont update tracking for jupe exempt users, these
197 * are likely to be spamtrap leaves
198 */
199 else if(IsExemptJupe(source_p))
200 aconf->port--;
201
202 continue;
203 }
204
205 if(splitmode && !IsOper(source_p) && (*name != '&') &&
206 ConfigChannel.no_join_on_split)
207 {
208 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
209 me.name, source_p->name, name);
210 continue;
211 }
212
213 if(*jbuf)
214 (void) strcat(jbuf, ",");
1f9de103 215 (void) rb_strlcat(jbuf, name, sizeof(jbuf));
212380e3
AC
216 }
217
218 if(parc > 2)
219 {
220 mykey = LOCAL_COPY(parv[2]);
4a2651e5 221 key = rb_strtok_r(mykey, ",", &p2);
212380e3
AC
222 }
223
4a2651e5
VY
224 for(name = rb_strtok_r(jbuf, ",", &p); name;
225 key = (key) ? rb_strtok_r(NULL, ",", &p2) : NULL, name = rb_strtok_r(NULL, ",", &p))
212380e3
AC
226 {
227 hook_data_channel_activity hook_info;
228
f4a80ce6
JT
229 /* JOIN 0 simply parts all channels the user is in */
230 if(*name == '0' && !atoi(name))
231 {
232 if(source_p->user->channel.head == NULL)
233 continue;
234
235 do_join_0(&me, source_p);
236 continue;
237 }
238
212380e3
AC
239 /* look for the channel */
240 if((chptr = find_channel(name)) != NULL)
241 {
242 if(IsMember(source_p, chptr))
243 continue;
244
245 flags = 0;
246 }
247 else
248 {
249 hook_data_client_approval moduledata;
250
251 moduledata.client = source_p;
252 moduledata.approved = 0;
253
254 call_hook(h_can_create_channel, &moduledata);
255
544cde90 256 if(moduledata.approved != 0)
212380e3
AC
257 {
258 sendto_one(source_p, form_str(moduledata.approved),
259 me.name, source_p->name, name);
260 continue;
261 }
262
263 if(splitmode && !IsOper(source_p) && (*name != '&') &&
264 ConfigChannel.no_create_on_split)
265 {
266 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
267 me.name, source_p->name, name);
268 continue;
269 }
270
271 flags = CHFL_CHANOP;
272 }
273
5b96d9a6 274 if((rb_dlink_list_length(&source_p->user->channel) >=
212380e3
AC
275 (unsigned long) ConfigChannel.max_chans_per_user) &&
276 (!IsOper(source_p) ||
5b96d9a6 277 (rb_dlink_list_length(&source_p->user->channel) >=
212380e3
AC
278 (unsigned long) ConfigChannel.max_chans_per_user * 3)))
279 {
280 sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
281 me.name, source_p->name, name);
cddbab51 282 continue;
212380e3
AC
283 }
284
212380e3
AC
285 if(chptr == NULL) /* If I already have a chptr, no point doing this */
286 {
287 chptr = get_or_create_channel(source_p, name, NULL);
288
289 if(chptr == NULL)
290 {
291 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
292 me.name, source_p->name, name);
212380e3
AC
293 continue;
294 }
295 }
296
765d839d
EM
297 /* If check_forward returns NULL, they couldn't join and there wasn't a usable forward channel. */
298 if(!(chptr2 = check_forward(source_p, chptr, key, &i)))
212380e3 299 {
765d839d
EM
300 /* might be wrong, but is there any other better location for such?
301 * see extensions/chm_operonly.c for other comments on this
302 * -- dwr
303 */
304 if(i != ERR_CUSTOM)
305 sendto_one(source_p, form_str(i), me.name, source_p->name, name);
acdf71d9 306
765d839d 307 continue;
212380e3 308 }
765d839d
EM
309 else if(chptr != chptr2)
310 sendto_one_numeric(source_p, ERR_LINKCHANNEL, form_str(ERR_LINKCHANNEL), name, chptr2->chname);
311
312 chptr = chptr2;
212380e3 313
ff91faaf
JT
314 if(flags == 0 &&
315 !IsOper(source_p) && !IsExemptSpambot(source_p))
cf3564d6
JT
316 check_spambot_warning(source_p, name);
317
212380e3
AC
318 /* add the user to the channel */
319 add_user_to_channel(chptr, source_p, flags);
320 if (chptr->mode.join_num &&
e3354945 321 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
212380e3
AC
322 {
323 chptr->join_count = 0;
e3354945 324 chptr->join_delta = rb_current_time();
212380e3
AC
325 }
326 chptr->join_count++;
327
328 /* we send the user their join here, because we could have to
329 * send a mode out next.
330 */
805cfa5a 331 send_channel_join(chptr, source_p);
212380e3
AC
332
333 /* its a new channel, set +nt and burst. */
334 if(flags & CHFL_CHANOP)
335 {
e3354945 336 chptr->channelts = rb_current_time();
212380e3
AC
337 chptr->mode.mode |= MODE_TOPICLIMIT;
338 chptr->mode.mode |= MODE_NOPRIVMSGS;
095efcf0 339 modes = channel_modes(chptr, &me);
212380e3 340
095efcf0
JT
341 sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s %s",
342 me.name, chptr->chname, modes);
212380e3 343
db2545b1
JT
344 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
345 ":%s SJOIN %ld %s %s :@%s",
346 me.id, (long) chptr->channelts,
347 chptr->chname, modes, source_p->id);
212380e3
AC
348 }
349 else
350 {
212380e3 351 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
bee3b671 352 ":%s JOIN %ld %s +",
212380e3 353 use_id(source_p), (long) chptr->channelts,
bee3b671 354 chptr->chname);
212380e3
AC
355 }
356
357 del_invite(chptr, source_p);
358
359 if(chptr->topic != NULL)
360 {
361 sendto_one(source_p, form_str(RPL_TOPIC), me.name,
362 source_p->name, chptr->chname, chptr->topic);
363
364 sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
365 me.name, source_p->name, chptr->chname,
366 chptr->topic_info, chptr->topic_time);
367 }
368
369 channel_member_names(chptr, source_p, 1);
370
212380e3
AC
371 hook_info.client = source_p;
372 hook_info.chptr = chptr;
373 hook_info.key = key;
374 call_hook(h_channel_join, &hook_info);
375 }
376
377 return 0;
378}
379
380/*
381 * ms_join
35835646
JT
382 * parv[1] = channel TS
383 * parv[2] = channel
384 * parv[3] = "+", formerly channel modes but now unused
385 * alternatively, a single "0" parameter parts all channels
212380e3
AC
386 */
387static int
388ms_join(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
389{
390 struct Channel *chptr;
bee3b671 391 static struct Mode mode;
212380e3
AC
392 time_t oldts;
393 time_t newts;
394 int isnew;
212380e3
AC
395 int keep_our_modes = YES;
396 int keep_new_modes = YES;
637c4932 397 rb_dlink_node *ptr, *next_ptr;
212380e3 398
f4a80ce6
JT
399 /* special case for join 0 */
400 if((parv[1][0] == '0') && (parv[1][1] == '\0') && parc == 2)
401 {
402 do_join_0(client_p, source_p);
403 return 0;
404 }
405
212380e3
AC
406 if(parc < 4)
407 return 0;
408
409 if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
410 return 0;
411
412 /* joins for local channels cant happen. */
413 if(parv[2][0] == '&')
414 return 0;
415
416 mbuf = modebuf;
417 mode.key[0] = mode.forward[0] = '\0';
418 mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
419
212380e3
AC
420 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
421 return 0;
422
423 newts = atol(parv[1]);
424 oldts = chptr->channelts;
212380e3
AC
425
426#ifdef IGNORE_BOGUS_TS
427 if(newts < 800000000)
428 {
429 sendto_realops_snomask(SNO_DEBUG, L_ALL,
430 "*** Bogus TS %ld on %s ignored from %s",
431 (long) newts, chptr->chname, client_p->name);
432 newts = (oldts == 0) ? oldts : 800000000;
433 }
434#else
435 /* making a channel TS0 */
436 if(!isnew && !newts && oldts)
437 {
438 sendto_channel_local(ALL_MEMBERS, chptr,
439 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to 0",
440 me.name, chptr->chname, chptr->chname, (long) oldts);
441 sendto_realops_snomask(SNO_GENERAL, L_ALL,
442 "Server %s changing TS on %s from %ld to 0",
443 source_p->name, chptr->chname, (long) oldts);
444 }
445#endif
446
447 if(isnew)
448 chptr->channelts = newts;
449 else if(newts == 0 || oldts == 0)
450 chptr->channelts = 0;
451 else if(newts == oldts)
452 ;
453 else if(newts < oldts)
454 {
455 keep_our_modes = NO;
456 chptr->channelts = newts;
457 }
458 else
459 keep_new_modes = NO;
460
212380e3
AC
461 /* Lost the TS, other side wins, so remove modes on this side */
462 if(!keep_our_modes)
463 {
bee3b671
JT
464 set_final_mode(&mode, &chptr->mode);
465 chptr->mode = mode;
212380e3 466 remove_our_modes(chptr, source_p);
637c4932 467 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
212380e3
AC
468 {
469 del_invite(chptr, ptr->data);
470 }
bee3b671
JT
471 /* If setting -j, clear join throttle state -- jilles */
472 chptr->join_count = chptr->join_delta = 0;
212380e3
AC
473 sendto_channel_local(ALL_MEMBERS, chptr,
474 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
475 me.name, chptr->chname, chptr->chname,
476 (long) oldts, (long) newts);
1117fbd3
JT
477 /* Update capitalization in channel name, this makes the
478 * capitalization timestamped like modes are -- jilles */
479 strcpy(chptr->chname, parv[2]);
bee3b671
JT
480 if(*modebuf != '\0')
481 sendto_channel_local(ALL_MEMBERS, chptr,
482 ":%s MODE %s %s %s",
483 source_p->servptr->name,
484 chptr->chname, modebuf, parabuf);
485 *modebuf = *parabuf = '\0';
6fb6bd15
AC
486
487 /* since we're dropping our modes, we want to clear the mlock as well. --nenolod */
488 set_channel_mlock(client_p, source_p, chptr, NULL, FALSE);
212380e3
AC
489 }
490
212380e3
AC
491 if(!IsMember(source_p, chptr))
492 {
493 add_user_to_channel(chptr, source_p, CHFL_PEON);
494 if (chptr->mode.join_num &&
e3354945 495 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
212380e3
AC
496 {
497 chptr->join_count = 0;
e3354945 498 chptr->join_delta = rb_current_time();
212380e3
AC
499 }
500 chptr->join_count++;
805cfa5a 501 send_channel_join(chptr, source_p);
212380e3
AC
502 }
503
212380e3 504 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
bee3b671
JT
505 ":%s JOIN %ld %s +",
506 source_p->id, (long) chptr->channelts, chptr->chname);
212380e3
AC
507 return 0;
508}
509
8cc12805
VY
510static int
511ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
512{
8cc12805
VY
513 static char buf_uid[BUFSIZE];
514 static const char empty_modes[] = "0";
515 struct Channel *chptr;
516 struct Client *target_p, *fakesource_p;
517 time_t newts;
518 time_t oldts;
519 static struct Mode mode, *oldmode;
520 const char *modes;
521 int args = 0;
522 int keep_our_modes = 1;
523 int keep_new_modes = 1;
524 int fl;
525 int isnew;
890423fb 526 int mlen_uid;
8cc12805
VY
527 int len_nick;
528 int len_uid;
529 int len;
530 int joins = 0;
531 const char *s;
8cc12805
VY
532 char *ptr_uid;
533 char *p;
534 int i, joinc = 0, timeslice = 0;
535 static char empty[] = "";
536 rb_dlink_node *ptr, *next_ptr;
537
538 if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
539 return 0;
540
541 /* SJOIN's for local channels can't happen. */
542 if(*parv[2] == '&')
543 return 0;
544
545 modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
546 pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
547
548 /* Hide connecting server on netburst -- jilles */
549 if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
550 fakesource_p = &me;
551 else
552 fakesource_p = source_p;
553
554 mbuf = modebuf;
555 newts = atol(parv[1]);
556
557 s = parv[3];
558 while (*s)
559 {
560 switch (*(s++))
561 {
8cc12805 562 case 'f':
f427c8b0 563 rb_strlcpy(mode.forward, parv[4 + args], sizeof(mode.forward));
8cc12805
VY
564 args++;
565 if(parc < 5 + args)
566 return 0;
567 break;
568 case 'j':
569 sscanf(parv[4 + args], "%d:%d", &joinc, &timeslice);
570 args++;
571 mode.join_num = joinc;
572 mode.join_time = timeslice;
573 if(parc < 5 + args)
574 return 0;
575 break;
576 case 'k':
f427c8b0 577 rb_strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
8cc12805
VY
578 args++;
579 if(parc < 5 + args)
580 return 0;
581 break;
582 case 'l':
583 mode.limit = atoi(parv[4 + args]);
584 args++;
585 if(parc < 5 + args)
586 return 0;
587 break;
efccc22c
VY
588 default:
589 if(chmode_flags[(int) *s] != 0)
590 {
591 mode.mode |= chmode_flags[(int) *s];
592 }
8cc12805
VY
593 }
594 }
595
596 if(parv[args + 4])
597 {
598 s = parv[args + 4];
599
600 /* remove any leading spaces */
601 while (*s == ' ')
602 s++;
603 }
604 else
605 s = "";
606
607 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
608 return 0; /* channel name too long? */
609
610
611 oldts = chptr->channelts;
612 oldmode = &chptr->mode;
613
614#ifdef IGNORE_BOGUS_TS
615 if(newts < 800000000)
616 {
617 sendto_realops_snomask(SNO_DEBUG, L_ALL,
618 "*** Bogus TS %ld on %s ignored from %s",
619 (long) newts, chptr->chname, client_p->name);
620
621 newts = (oldts == 0) ? oldts : 800000000;
622 }
623#else
624 if(!isnew && !newts && oldts)
625 {
626 sendto_channel_local(ALL_MEMBERS, chptr,
627 ":%s NOTICE %s :*** Notice -- TS for %s "
628 "changed from %ld to 0",
629 me.name, chptr->chname, chptr->chname, (long) oldts);
630 sendto_realops_snomask(SNO_GENERAL, L_ALL,
631 "Server %s changing TS on %s from %ld to 0",
632 source_p->name, chptr->chname, (long) oldts);
633 }
634#endif
635
636 if(isnew)
637 chptr->channelts = newts;
638
639 else if(newts == 0 || oldts == 0)
640 chptr->channelts = 0;
641 else if(newts == oldts)
642 ;
643 else if(newts < oldts)
644 {
645 /* If configured, kick people trying to join +i/+k
646 * channels by recreating them on split servers.
a1574df4
JT
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.
8cc12805
VY
652 * -- jilles */
653 if (ConfigChannel.kick_on_split_riding &&
a1574df4
JT
654 ((!HasSentEob(source_p) &&
655 mode.mode & MODE_INVITEONLY) ||
8cc12805
VY
656 (mode.key[0] != 0 && irccmp(mode.key, oldmode->key) != 0)))
657 {
658 struct membership *msptr;
659 struct Client *who;
660 int l = rb_dlink_list_length(&chptr->members);
8cc12805
VY
661
662 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
663 {
664 msptr = ptr->data;
665 who = msptr->client_p;
666 sendto_one(who, ":%s KICK %s %s :Net Rider",
667 me.name, chptr->chname, who->name);
668
669 sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
670 ":%s KICK %s %s :Net Rider",
671 me.id, chptr->chname,
672 who->id);
8cc12805
VY
673 remove_user_from_channel(msptr);
674 if (--l == 0)
675 break;
676 }
677 if (l == 0)
678 {
679 /* Channel was emptied, create a new one */
680 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
681 return 0; /* oops! */
682
8cc12805
VY
683 oldmode = &chptr->mode;
684 }
685 }
686 keep_our_modes = NO;
687 chptr->channelts = newts;
688 }
689 else
690 keep_new_modes = NO;
691
692 if(!keep_new_modes)
693 mode = *oldmode;
694 else if(keep_our_modes)
695 {
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 strcpy(mode.key, oldmode->key);
701 if(oldmode->join_num > mode.join_num ||
702 (oldmode->join_num == mode.join_num &&
703 oldmode->join_time > mode.join_time))
704 {
705 mode.join_num = oldmode->join_num;
706 mode.join_time = oldmode->join_time;
707 }
708 if(irccmp(mode.forward, oldmode->forward) < 0)
709 strcpy(mode.forward, oldmode->forward);
710 }
711 else
712 {
713 /* If setting -j, clear join throttle state -- jilles */
714 if (!mode.join_num)
715 chptr->join_count = chptr->join_delta = 0;
716 }
717
718 set_final_mode(&mode, oldmode);
719 chptr->mode = mode;
720
721 /* Lost the TS, other side wins, so remove modes on this side */
722 if(!keep_our_modes)
723 {
724 remove_our_modes(chptr, fakesource_p);
725 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
726 {
727 del_invite(chptr, ptr->data);
728 }
7b22c84f
JT
729
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,
734 'e', ONLY_CHANOPS);
735 if(rb_dlink_list_length(&chptr->invexlist) > 0)
736 remove_ban_list(chptr, fakesource_p, &chptr->invexlist,
737 'I', ONLY_CHANOPS);
738 if(rb_dlink_list_length(&chptr->quietlist) > 0)
739 remove_ban_list(chptr, fakesource_p, &chptr->quietlist,
740 'q', ALL_MEMBERS);
741 chptr->bants++;
742
8cc12805
VY
743 sendto_channel_local(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]);
6fb6bd15
AC
750
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);
8cc12805
VY
753 }
754
755 if(*modebuf != '\0')
756 sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
757 fakesource_p->name, chptr->chname, modebuf, parabuf);
758
759 *modebuf = *parabuf = '\0';
760
761 if(parv[3][0] != '0' && keep_new_modes)
762 modes = channel_modes(chptr, source_p);
763 else
764 modes = empty_modes;
765
8cc12805
VY
766 mlen_uid = rb_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;
769
770 mbuf = modebuf;
771 para[0] = para[1] = para[2] = para[3] = empty;
772 pargs = 0;
773 len_nick = len_uid = 0;
774
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
777 * second nick
778 */
779 if((p = strchr(s, ' ')) != NULL)
780 {
781 *p++ = '\0';
782 }
783
784 *mbuf++ = '+';
785
786 while (s)
787 {
788 fl = 0;
789
790 for (i = 0; i < 2; i++)
791 {
792 if(*s == '@')
793 {
794 fl |= CHFL_CHANOP;
795 s++;
796 }
797 else if(*s == '+')
798 {
799 fl |= CHFL_VOICE;
800 s++;
801 }
802 }
803
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))
807 goto nextnick;
808
809 /* we assume for these we can fit at least one nick/uid in.. */
810
811 /* check we can fit another status+nick+space into a buffer */
8cc12805
VY
812 if((mlen_uid + len_uid + IDLEN + 3) > (BUFSIZE - 3))
813 {
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;
817 len_uid = 0;
818 }
819
820 if(keep_new_modes)
821 {
822 if(fl & CHFL_CHANOP)
823 {
8cc12805
VY
824 *ptr_uid++ = '@';
825 len_nick++;
826 len_uid++;
827 }
828 if(fl & CHFL_VOICE)
829 {
8cc12805
VY
830 *ptr_uid++ = '+';
831 len_nick++;
832 len_uid++;
833 }
834 }
835
836 /* copy the nick to the two buffers */
8cc12805
VY
837 len = rb_sprintf(ptr_uid, "%s ", use_id(target_p));
838 ptr_uid += len;
839 len_uid += len;
840
841 if(!keep_new_modes)
842 fl = 0;
843
844 if(!IsMember(target_p, chptr))
845 {
846 add_user_to_channel(chptr, target_p, fl);
805cfa5a 847 send_channel_join(chptr, target_p);
8cc12805
VY
848 joins++;
849 }
850
851 if(fl & CHFL_CHANOP)
852 {
853 *mbuf++ = 'o';
854 para[pargs++] = target_p->name;
855
856 /* a +ov user.. bleh */
857 if(fl & CHFL_VOICE)
858 {
859 /* its possible the +o has filled up MAXMODEPARAMS, if so, start
860 * a new buffer
861 */
862 if(pargs >= MAXMODEPARAMS)
863 {
864 *mbuf = '\0';
865 sendto_channel_local(ALL_MEMBERS, chptr,
866 ":%s MODE %s %s %s %s %s %s",
867 fakesource_p->name, chptr->chname,
868 modebuf,
869 para[0], para[1], para[2], para[3]);
870 mbuf = modebuf;
871 *mbuf++ = '+';
872 para[0] = para[1] = para[2] = para[3] = NULL;
873 pargs = 0;
874 }
875
876 *mbuf++ = 'v';
877 para[pargs++] = target_p->name;
878 }
879 }
880 else if(fl & CHFL_VOICE)
881 {
882 *mbuf++ = 'v';
883 para[pargs++] = target_p->name;
884 }
885
886 if(pargs >= MAXMODEPARAMS)
887 {
888 *mbuf = '\0';
889 sendto_channel_local(ALL_MEMBERS, chptr,
890 ":%s MODE %s %s %s %s %s %s",
891 fakesource_p->name,
892 chptr->chname,
893 modebuf, para[0], para[1], para[2], para[3]);
894 mbuf = modebuf;
895 *mbuf++ = '+';
896 para[0] = para[1] = para[2] = para[3] = NULL;
897 pargs = 0;
898 }
899
900 nextnick:
901 /* p points to the next nick */
902 s = p;
903
904 /* if there was a trailing space and p was pointing to it, then we
905 * need to exit.. this has the side effect of breaking double spaces
906 * in an sjoin.. but that shouldnt happen anyway
907 */
908 if(s && (*s == '\0'))
909 s = p = NULL;
910
911 /* if p was NULL due to no spaces, s wont exist due to the above, so
912 * we cant check it for spaces.. if there are no spaces, then when
913 * we next get here, s will be NULL
914 */
915 if(s && ((p = strchr(s, ' ')) != NULL))
916 {
917 *p++ = '\0';
918 }
919 }
920
921 *mbuf = '\0';
922 if(pargs)
923 {
924 sendto_channel_local(ALL_MEMBERS, chptr,
925 ":%s MODE %s %s %s %s %s %s",
926 fakesource_p->name, chptr->chname, modebuf,
927 para[0], CheckEmpty(para[1]),
928 CheckEmpty(para[2]), CheckEmpty(para[3]));
929 }
930
931 if(!joins && !(chptr->mode.mode & MODE_PERMANENT) && isnew)
932 {
933 destroy_channel(chptr);
934
935 return 0;
936 }
937
938 /* Keep the colon if we're sending an SJOIN without nicks -- jilles */
939 if (joins)
940 {
8cc12805
VY
941 *(ptr_uid - 1) = '\0';
942 }
943
944 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
8cc12805 945
8cc12805
VY
946 return 0;
947}
948
f4a80ce6
JT
949/*
950 * do_join_0
951 *
952 * inputs - pointer to client doing join 0
953 * output - NONE
954 * side effects - Use has decided to join 0. This is legacy
955 * from the days when channels were numbers not names. *sigh*
f4a80ce6
JT
956 */
957static void
958do_join_0(struct Client *client_p, struct Client *source_p)
959{
960 struct membership *msptr;
961 struct Channel *chptr = NULL;
5b96d9a6 962 rb_dlink_node *ptr;
f4a80ce6
JT
963
964 /* Finish the flood grace period... */
965 if(MyClient(source_p) && !IsFloodDone(source_p))
966 flood_endgrace(source_p);
967
f4a80ce6 968 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s JOIN 0", use_id(source_p));
f4a80ce6 969
f4a80ce6
JT
970 while((ptr = source_p->user->channel.head))
971 {
4eb9a3ca
JT
972 if(MyConnect(source_p) &&
973 !IsOper(source_p) && !IsExemptSpambot(source_p))
974 check_spambot_warning(source_p, NULL);
975
f4a80ce6
JT
976 msptr = ptr->data;
977 chptr = msptr->chptr;
978 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
979 source_p->name,
980 source_p->username, source_p->host, chptr->chname);
981 remove_user_from_channel(msptr);
982 }
983}
984
212380e3
AC
985static int
986check_channel_name_loc(struct Client *source_p, const char *name)
987{
6865c0b0
JT
988 const char *p;
989
212380e3
AC
990 s_assert(name != NULL);
991 if(EmptyString(name))
992 return 0;
993
994 if(ConfigFileEntry.disable_fake_channels && !IsOper(source_p))
995 {
6865c0b0 996 for(p = name; *p; ++p)
212380e3 997 {
6865c0b0 998 if(!IsChanChar(*p) || IsFakeChanChar(*p))
212380e3
AC
999 return 0;
1000 }
1001 }
1002 else
1003 {
6865c0b0 1004 for(p = name; *p; ++p)
212380e3 1005 {
6865c0b0 1006 if(!IsChanChar(*p))
212380e3
AC
1007 return 0;
1008 }
1009 }
1010
6865c0b0
JT
1011 if(ConfigChannel.only_ascii_channels)
1012 {
1013 for(p = name; *p; ++p)
1014 if(*p < 33 || *p > 126)
1015 return 0;
1016 }
1017
212380e3
AC
1018 return 1;
1019}
1020
212380e3
AC
1021static void
1022set_final_mode(struct Mode *mode, struct Mode *oldmode)
1023{
1024 int dir = MODE_QUERY;
1025 char *pbuf = parabuf;
1026 int len;
1027 int i;
1028
1029 /* ok, first get a list of modes we need to add */
efccc22c 1030 for (i = 0; i < 256; i++)
212380e3 1031 {
efccc22c 1032 if((mode->mode & chmode_flags[i]) && !(oldmode->mode & chmode_flags[i]))
212380e3
AC
1033 {
1034 if(dir != MODE_ADD)
1035 {
1036 *mbuf++ = '+';
1037 dir = MODE_ADD;
1038 }
efccc22c 1039 *mbuf++ = i;
212380e3
AC
1040 }
1041 }
1042
1043 /* now the ones we need to remove. */
efccc22c 1044 for (i = 0; i < 256; i++)
212380e3 1045 {
efccc22c 1046 if((oldmode->mode & chmode_flags[i]) && !(mode->mode & chmode_flags[i]))
212380e3
AC
1047 {
1048 if(dir != MODE_DEL)
1049 {
1050 *mbuf++ = '-';
1051 dir = MODE_DEL;
1052 }
efccc22c 1053 *mbuf++ = i;
212380e3
AC
1054 }
1055 }
1056
1057 if(oldmode->limit && !mode->limit)
1058 {
1059 if(dir != MODE_DEL)
1060 {
1061 *mbuf++ = '-';
1062 dir = MODE_DEL;
1063 }
1064 *mbuf++ = 'l';
1065 }
1066 if(oldmode->key[0] && !mode->key[0])
1067 {
1068 if(dir != MODE_DEL)
1069 {
1070 *mbuf++ = '-';
1071 dir = MODE_DEL;
1072 }
1073 *mbuf++ = 'k';
7cdb0a09 1074 len = rb_sprintf(pbuf, "%s ", oldmode->key);
212380e3
AC
1075 pbuf += len;
1076 }
1077 if(oldmode->join_num && !mode->join_num)
1078 {
1079 if(dir != MODE_DEL)
1080 {
1081 *mbuf++ = '-';
1082 dir = MODE_DEL;
1083 }
1084 *mbuf++ = 'j';
1085 }
1086 if(oldmode->forward[0] && !mode->forward[0])
1087 {
1088 if(dir != MODE_DEL)
1089 {
1090 *mbuf++ = '-';
1091 dir = MODE_DEL;
1092 }
1093 *mbuf++ = 'f';
1094 }
1095 if(mode->limit && oldmode->limit != mode->limit)
1096 {
1097 if(dir != MODE_ADD)
1098 {
1099 *mbuf++ = '+';
1100 dir = MODE_ADD;
1101 }
1102 *mbuf++ = 'l';
7cdb0a09 1103 len = rb_sprintf(pbuf, "%d ", mode->limit);
212380e3
AC
1104 pbuf += len;
1105 }
1106 if(mode->key[0] && strcmp(oldmode->key, mode->key))
1107 {
1108 if(dir != MODE_ADD)
1109 {
1110 *mbuf++ = '+';
1111 dir = MODE_ADD;
1112 }
1113 *mbuf++ = 'k';
7cdb0a09 1114 len = rb_sprintf(pbuf, "%s ", mode->key);
212380e3
AC
1115 pbuf += len;
1116 }
1117 if(mode->join_num && (oldmode->join_num != mode->join_num || oldmode->join_time != mode->join_time))
1118 {
1119 if(dir != MODE_ADD)
1120 {
1121 *mbuf++ = '+';
1122 dir = MODE_ADD;
1123 }
1124 *mbuf++ = 'j';
7cdb0a09 1125 len = rb_sprintf(pbuf, "%d:%d ", mode->join_num, mode->join_time);
212380e3
AC
1126 pbuf += len;
1127 }
765d839d 1128 if(mode->forward[0] && strcmp(oldmode->forward, mode->forward))
212380e3
AC
1129 {
1130 if(dir != MODE_ADD)
1131 {
1132 *mbuf++ = '+';
1133 dir = MODE_ADD;
1134 }
1135 *mbuf++ = 'f';
7cdb0a09 1136 len = rb_sprintf(pbuf, "%s ", mode->forward);
212380e3
AC
1137 pbuf += len;
1138 }
1139 *mbuf = '\0';
1140}
1141
1142/*
1143 * remove_our_modes
1144 *
1145 * inputs -
1146 * output -
1147 * side effects -
1148 */
1149static void
1150remove_our_modes(struct Channel *chptr, struct Client *source_p)
1151{
1152 struct membership *msptr;
5b96d9a6 1153 rb_dlink_node *ptr;
212380e3
AC
1154 char lmodebuf[MODEBUFLEN];
1155 char *lpara[MAXMODEPARAMS];
1156 int count = 0;
1157 int i;
1158
1159 mbuf = lmodebuf;
1160 *mbuf++ = '-';
1161
1162 for(i = 0; i < MAXMODEPARAMS; i++)
1163 lpara[i] = NULL;
1164
5b96d9a6 1165 RB_DLINK_FOREACH(ptr, chptr->members.head)
212380e3
AC
1166 {
1167 msptr = ptr->data;
1168
1169 if(is_chanop(msptr))
1170 {
1171 msptr->flags &= ~CHFL_CHANOP;
1172 lpara[count++] = msptr->client_p->name;
1173 *mbuf++ = 'o';
1174
1175 /* +ov, might not fit so check. */
1176 if(is_voiced(msptr))
1177 {
1178 if(count >= MAXMODEPARAMS)
1179 {
1180 *mbuf = '\0';
1181 sendto_channel_local(ALL_MEMBERS, chptr,
1182 ":%s MODE %s %s %s %s %s %s",
7bf78de0 1183 source_p->name, chptr->chname,
212380e3
AC
1184 lmodebuf, lpara[0], lpara[1],
1185 lpara[2], lpara[3]);
1186
1187 /* preserve the initial '-' */
1188 mbuf = lmodebuf;
1189 *mbuf++ = '-';
1190 count = 0;
1191
1192 for(i = 0; i < MAXMODEPARAMS; i++)
1193 lpara[i] = NULL;
1194 }
1195
1196 msptr->flags &= ~CHFL_VOICE;
1197 lpara[count++] = msptr->client_p->name;
1198 *mbuf++ = 'v';
1199 }
1200 }
1201 else if(is_voiced(msptr))
1202 {
1203 msptr->flags &= ~CHFL_VOICE;
1204 lpara[count++] = msptr->client_p->name;
1205 *mbuf++ = 'v';
1206 }
1207 else
1208 continue;
1209
1210 if(count >= MAXMODEPARAMS)
1211 {
1212 *mbuf = '\0';
1213 sendto_channel_local(ALL_MEMBERS, chptr,
1214 ":%s MODE %s %s %s %s %s %s",
7bf78de0 1215 source_p->name, chptr->chname, lmodebuf,
212380e3
AC
1216 lpara[0], lpara[1], lpara[2], lpara[3]);
1217 mbuf = lmodebuf;
1218 *mbuf++ = '-';
1219 count = 0;
1220
1221 for(i = 0; i < MAXMODEPARAMS; i++)
1222 lpara[i] = NULL;
1223 }
1224 }
1225
1226 if(count != 0)
1227 {
1228 *mbuf = '\0';
1229 sendto_channel_local(ALL_MEMBERS, chptr,
1230 ":%s MODE %s %s %s %s %s %s",
7bf78de0 1231 source_p->name, chptr->chname, lmodebuf,
212380e3
AC
1232 EmptyString(lpara[0]) ? "" : lpara[0],
1233 EmptyString(lpara[1]) ? "" : lpara[1],
1234 EmptyString(lpara[2]) ? "" : lpara[2],
1235 EmptyString(lpara[3]) ? "" : lpara[3]);
1236
1237 }
1238}
8cc12805
VY
1239
1240/* remove_ban_list()
1241 *
1242 * inputs - channel, source, list to remove, char of mode, caps needed
1243 * outputs -
1244 * side effects - given list is removed, with modes issued to local clients
8cc12805
VY
1245 */
1246static void
1247remove_ban_list(struct Channel *chptr, struct Client *source_p,
8afeb720 1248 rb_dlink_list * list, char c, int mems)
8cc12805
VY
1249{
1250 static char lmodebuf[BUFSIZE];
1251 static char lparabuf[BUFSIZE];
1252 struct Ban *banptr;
1253 rb_dlink_node *ptr;
1254 rb_dlink_node *next_ptr;
1255 char *pbuf;
1256 int count = 0;
1257 int cur_len, mlen, plen;
1258
1259 pbuf = lparabuf;
1260
1261 cur_len = mlen = rb_sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
1262 mbuf = lmodebuf + mlen;
1263
1264 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
1265 {
1266 banptr = ptr->data;
1267
1268 /* trailing space, and the mode letter itself */
1269 plen = strlen(banptr->banstr) + 2;
1270
1271 if(count >= MAXMODEPARAMS || (cur_len + plen) > BUFSIZE - 4)
1272 {
1273 /* remove trailing space */
1274 *mbuf = '\0';
1275 *(pbuf - 1) = '\0';
1276
1277 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
8cc12805
VY
1278
1279 cur_len = mlen;
1280 mbuf = lmodebuf + mlen;
1281 pbuf = lparabuf;
1282 count = 0;
1283 }
1284
1285 *mbuf++ = c;
1286 cur_len += plen;
1287 pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr);
1288 count++;
1289
1290 free_ban(banptr);
1291 }
1292
1293 *mbuf = '\0';
1294 *(pbuf - 1) = '\0';
1295 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
8cc12805
VY
1296
1297 list->head = list->tail = NULL;
1298 list->length = 0;
1299}