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