]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/core/m_join.c
Remove dead code: last_join_time is already updated by check_spambot_warning().
[irc/rqf/shadowircd.git] / modules / core / m_join.c
CommitLineData
212380e3 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 25 */
26
27#include "stdinc.h"
212380e3 28#include "channel.h"
29#include "client.h"
30#include "common.h"
31#include "hash.h"
13ae2f4b 32#include "match.h"
212380e3 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"
7608ef49 43#include "chmode.h"
212380e3 44
45static int m_join(struct Client *, struct Client *, int, const char **);
46static int ms_join(struct Client *, struct Client *, int, const char **);
452382d0 47static int ms_sjoin(struct Client *, struct Client *, int, const char **);
212380e3 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
452382d0
VY
57struct Message sjoin_msgtab = {
58 "SJOIN", 0, 0, 0, MFLG_SLOW,
767394f0 59 {mg_unreg, mg_ignore, mg_ignore, {ms_sjoin, 4}, mg_ignore, mg_ignore}
452382d0
VY
60};
61
62mapi_clist_av1 join_clist[] = { &join_msgtab, &sjoin_msgtab, NULL };
212380e3 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 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
452382d0 78static void remove_ban_list(struct Channel *chptr, struct Client *source_p,
0a70e150 79 rb_dlink_list * list, char c, int mems);
452382d0 80
212380e3 81static char modebuf[MODEBUFLEN];
82static char parabuf[MODEBUFLEN];
452382d0 83static const char *para[MAXMODEPARAMS];
212380e3 84static char *mbuf;
452382d0 85static int pargs;
212380e3 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 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;
b3be8599 139 const char *modes;
212380e3 140 int i, flags = 0;
141 char *p = NULL, *p2 = NULL;
142 char *chanlist;
143 char *mykey;
212380e3 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]);
dcbd1d07 151 for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
212380e3 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 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 */
169 else if(!IsChannelName(name))
170 {
171 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
172 form_str(ERR_NOSUCHCHANNEL), name);
173 continue;
174 }
175
176 /* see if its resv'd */
177 if(!IsExemptResv(source_p) && (aconf = hash_find_resv(name)))
178 {
179 sendto_one_numeric(source_p, ERR_BADCHANNAME,
180 form_str(ERR_BADCHANNAME), name);
181
182 /* dont warn for opers */
183 if(!IsExemptJupe(source_p) && !IsOper(source_p))
184 sendto_realops_snomask(SNO_SPY, L_NETWIDE,
185 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
186 source_p->name, source_p->username,
63aecfb9 187 source_p->orighost, name, aconf->passwd);
212380e3 188 /* dont update tracking for jupe exempt users, these
189 * are likely to be spamtrap leaves
190 */
191 else if(IsExemptJupe(source_p))
192 aconf->port--;
193
194 continue;
195 }
196
197 if(splitmode && !IsOper(source_p) && (*name != '&') &&
198 ConfigChannel.no_join_on_split)
199 {
200 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
201 me.name, source_p->name, name);
202 continue;
203 }
204
205 if(*jbuf)
206 (void) strcat(jbuf, ",");
a64c5173 207 (void) rb_strlcat(jbuf, name, sizeof(jbuf));
212380e3 208 }
209
210 if(parc > 2)
211 {
212 mykey = LOCAL_COPY(parv[2]);
dcbd1d07 213 key = rb_strtok_r(mykey, ",", &p2);
212380e3 214 }
215
dcbd1d07
VY
216 for(name = rb_strtok_r(jbuf, ",", &p); name;
217 key = (key) ? rb_strtok_r(NULL, ",", &p2) : NULL, name = rb_strtok_r(NULL, ",", &p))
212380e3 218 {
219 hook_data_channel_activity hook_info;
220
f4a80ce6 221 /* JOIN 0 simply parts all channels the user is in */
222 if(*name == '0' && !atoi(name))
223 {
224 if(source_p->user->channel.head == NULL)
225 continue;
226
227 do_join_0(&me, source_p);
228 continue;
229 }
230
212380e3 231 /* look for the channel */
232 if((chptr = find_channel(name)) != NULL)
233 {
234 if(IsMember(source_p, chptr))
235 continue;
236
237 flags = 0;
238 }
239 else
240 {
241 hook_data_client_approval moduledata;
242
243 moduledata.client = source_p;
244 moduledata.approved = 0;
245
246 call_hook(h_can_create_channel, &moduledata);
247
544cde90 248 if(moduledata.approved != 0)
212380e3 249 {
250 sendto_one(source_p, form_str(moduledata.approved),
251 me.name, source_p->name, name);
252 continue;
253 }
254
255 if(splitmode && !IsOper(source_p) && (*name != '&') &&
256 ConfigChannel.no_create_on_split)
257 {
258 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
259 me.name, source_p->name, name);
260 continue;
261 }
262
263 flags = CHFL_CHANOP;
264 }
265
08d11e34 266 if((rb_dlink_list_length(&source_p->user->channel) >=
212380e3 267 (unsigned long) ConfigChannel.max_chans_per_user) &&
268 (!IsOper(source_p) ||
08d11e34 269 (rb_dlink_list_length(&source_p->user->channel) >=
212380e3 270 (unsigned long) ConfigChannel.max_chans_per_user * 3)))
271 {
272 sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
273 me.name, source_p->name, name);
212380e3 274 return 0;
275 }
276
212380e3 277 if(chptr == NULL) /* If I already have a chptr, no point doing this */
278 {
279 chptr = get_or_create_channel(source_p, name, NULL);
280
281 if(chptr == NULL)
282 {
283 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
284 me.name, source_p->name, name);
212380e3 285 continue;
286 }
287 }
288
212380e3 289 /* can_join checks for +i key, bans etc */
290 if((i = can_join(source_p, chptr, key)))
291 {
292 if ((i != ERR_NEEDREGGEDNICK && i != ERR_THROTTLE && i != ERR_INVITEONLYCHAN && i != ERR_CHANNELISFULL) ||
293 (!ConfigChannel.use_forward || (chptr = check_forward(source_p, chptr, key)) == NULL))
294 {
7608ef49
VY
295 /* might be wrong, but is there any other better location for such?
296 * see extensions/chm_operonly.c for other comments on this
297 * -- dwr
298 */
299 if(i != ERR_CUSTOM)
300 sendto_one(source_p, form_str(i), me.name, source_p->name, name);
301
212380e3 302 continue;
303 }
7608ef49 304
212380e3 305 sendto_one_numeric(source_p, ERR_LINKCHANNEL, form_str(ERR_LINKCHANNEL), name, chptr->chname);
306 }
307
d5e959f1
JT
308 if(!IsOper(source_p) && !IsExemptSpambot(source_p))
309 check_spambot_warning(source_p, name);
310
212380e3 311 /* add the user to the channel */
312 add_user_to_channel(chptr, source_p, flags);
313 if (chptr->mode.join_num &&
9f6bbe3c 314 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
212380e3 315 {
316 chptr->join_count = 0;
9f6bbe3c 317 chptr->join_delta = rb_current_time();
212380e3 318 }
319 chptr->join_count++;
320
321 /* we send the user their join here, because we could have to
322 * send a mode out next.
323 */
324 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
325 source_p->name,
326 source_p->username, source_p->host, chptr->chname);
327
328 /* its a new channel, set +nt and burst. */
329 if(flags & CHFL_CHANOP)
330 {
9f6bbe3c 331 chptr->channelts = rb_current_time();
212380e3 332 chptr->mode.mode |= MODE_TOPICLIMIT;
333 chptr->mode.mode |= MODE_NOPRIVMSGS;
b3be8599 334 modes = channel_modes(chptr, &me);
212380e3 335
b3be8599
JT
336 sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s %s",
337 me.name, chptr->chname, modes);
212380e3 338
060ea02e
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 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 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 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
9d350156
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 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 387 time_t oldts;
388 time_t newts;
389 int isnew;
212380e3 390 int keep_our_modes = YES;
391 int keep_new_modes = YES;
90a3c35b 392 rb_dlink_node *ptr, *next_ptr;
212380e3 393
f4a80ce6 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 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 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 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 456 /* Lost the TS, other side wins, so remove modes on this side */
457 if(!keep_our_modes)
458 {
bee3b671 459 set_final_mode(&mode, &chptr->mode);
460 chptr->mode = mode;
212380e3 461 remove_our_modes(chptr, source_p);
90a3c35b 462 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
212380e3 463 {
464 del_invite(chptr, ptr->data);
465 }
bee3b671 466 /* If setting -j, clear join throttle state -- jilles */
467 chptr->join_count = chptr->join_delta = 0;
212380e3 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 472 /* Update capitalization in channel name, this makes the
473 * capitalization timestamped like modes are -- jilles */
474 strcpy(chptr->chname, parv[2]);
bee3b671 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';
212380e3 481 }
482
212380e3 483 if(!IsMember(source_p, chptr))
484 {
485 add_user_to_channel(chptr, source_p, CHFL_PEON);
486 if (chptr->mode.join_num &&
9f6bbe3c 487 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
212380e3 488 {
489 chptr->join_count = 0;
9f6bbe3c 490 chptr->join_delta = rb_current_time();
212380e3 491 }
492 chptr->join_count++;
493 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
494 source_p->name, source_p->username,
495 source_p->host, chptr->chname);
496 }
497
212380e3 498 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
bee3b671 499 ":%s JOIN %ld %s +",
500 source_p->id, (long) chptr->channelts, chptr->chname);
212380e3 501 return 0;
502}
503
452382d0
VY
504static int
505ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
506{
452382d0
VY
507 static char buf_uid[BUFSIZE];
508 static const char empty_modes[] = "0";
509 struct Channel *chptr;
510 struct Client *target_p, *fakesource_p;
511 time_t newts;
512 time_t oldts;
513 static struct Mode mode, *oldmode;
514 const char *modes;
515 int args = 0;
516 int keep_our_modes = 1;
517 int keep_new_modes = 1;
518 int fl;
519 int isnew;
26476173 520 int mlen_uid;
452382d0
VY
521 int len_nick;
522 int len_uid;
523 int len;
524 int joins = 0;
525 const char *s;
452382d0
VY
526 char *ptr_uid;
527 char *p;
528 int i, joinc = 0, timeslice = 0;
529 static char empty[] = "";
530 rb_dlink_node *ptr, *next_ptr;
531
532 if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
533 return 0;
534
535 /* SJOIN's for local channels can't happen. */
536 if(*parv[2] == '&')
537 return 0;
538
539 modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
540 pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
541
542 /* Hide connecting server on netburst -- jilles */
543 if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
544 fakesource_p = &me;
545 else
546 fakesource_p = source_p;
547
548 mbuf = modebuf;
549 newts = atol(parv[1]);
550
551 s = parv[3];
552 while (*s)
553 {
554 switch (*(s++))
555 {
452382d0 556 case 'f':
907468c4 557 rb_strlcpy(mode.forward, parv[4 + args], sizeof(mode.forward));
452382d0
VY
558 args++;
559 if(parc < 5 + args)
560 return 0;
561 break;
562 case 'j':
563 sscanf(parv[4 + args], "%d:%d", &joinc, &timeslice);
564 args++;
565 mode.join_num = joinc;
566 mode.join_time = timeslice;
567 if(parc < 5 + args)
568 return 0;
569 break;
570 case 'k':
907468c4 571 rb_strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
452382d0
VY
572 args++;
573 if(parc < 5 + args)
574 return 0;
575 break;
576 case 'l':
577 mode.limit = atoi(parv[4 + args]);
578 args++;
579 if(parc < 5 + args)
580 return 0;
581 break;
75818939
VY
582 default:
583 if(chmode_flags[(int) *s] != 0)
584 {
585 mode.mode |= chmode_flags[(int) *s];
586 }
452382d0
VY
587 }
588 }
589
590 if(parv[args + 4])
591 {
592 s = parv[args + 4];
593
594 /* remove any leading spaces */
595 while (*s == ' ')
596 s++;
597 }
598 else
599 s = "";
600
601 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
602 return 0; /* channel name too long? */
603
604
605 oldts = chptr->channelts;
606 oldmode = &chptr->mode;
607
608#ifdef IGNORE_BOGUS_TS
609 if(newts < 800000000)
610 {
611 sendto_realops_snomask(SNO_DEBUG, L_ALL,
612 "*** Bogus TS %ld on %s ignored from %s",
613 (long) newts, chptr->chname, client_p->name);
614
615 newts = (oldts == 0) ? oldts : 800000000;
616 }
617#else
618 if(!isnew && !newts && oldts)
619 {
620 sendto_channel_local(ALL_MEMBERS, chptr,
621 ":%s NOTICE %s :*** Notice -- TS for %s "
622 "changed from %ld to 0",
623 me.name, chptr->chname, chptr->chname, (long) oldts);
624 sendto_realops_snomask(SNO_GENERAL, L_ALL,
625 "Server %s changing TS on %s from %ld to 0",
626 source_p->name, chptr->chname, (long) oldts);
627 }
628#endif
629
630 if(isnew)
631 chptr->channelts = newts;
632
633 else if(newts == 0 || oldts == 0)
634 chptr->channelts = 0;
635 else if(newts == oldts)
636 ;
637 else if(newts < oldts)
638 {
639 /* If configured, kick people trying to join +i/+k
640 * channels by recreating them on split servers.
641 * Don't kick if the source has sent EOB (services
642 * deopping everyone by TS-1 SJOIN).
643 * -- jilles */
644 if (ConfigChannel.kick_on_split_riding &&
645 !HasSentEob(source_p) &&
646 ((mode.mode & MODE_INVITEONLY) ||
647 (mode.key[0] != 0 && irccmp(mode.key, oldmode->key) != 0)))
648 {
649 struct membership *msptr;
650 struct Client *who;
651 int l = rb_dlink_list_length(&chptr->members);
452382d0
VY
652
653 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
654 {
655 msptr = ptr->data;
656 who = msptr->client_p;
657 sendto_one(who, ":%s KICK %s %s :Net Rider",
658 me.name, chptr->chname, who->name);
659
660 sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
661 ":%s KICK %s %s :Net Rider",
662 me.id, chptr->chname,
663 who->id);
452382d0
VY
664 remove_user_from_channel(msptr);
665 if (--l == 0)
666 break;
667 }
668 if (l == 0)
669 {
670 /* Channel was emptied, create a new one */
671 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
672 return 0; /* oops! */
673
452382d0
VY
674 oldmode = &chptr->mode;
675 }
676 }
677 keep_our_modes = NO;
678 chptr->channelts = newts;
679 }
680 else
681 keep_new_modes = NO;
682
683 if(!keep_new_modes)
684 mode = *oldmode;
685 else if(keep_our_modes)
686 {
687 mode.mode |= oldmode->mode;
688 if(oldmode->limit > mode.limit)
689 mode.limit = oldmode->limit;
690 if(strcmp(mode.key, oldmode->key) < 0)
691 strcpy(mode.key, oldmode->key);
692 if(oldmode->join_num > mode.join_num ||
693 (oldmode->join_num == mode.join_num &&
694 oldmode->join_time > mode.join_time))
695 {
696 mode.join_num = oldmode->join_num;
697 mode.join_time = oldmode->join_time;
698 }
699 if(irccmp(mode.forward, oldmode->forward) < 0)
700 strcpy(mode.forward, oldmode->forward);
701 }
702 else
703 {
704 /* If setting -j, clear join throttle state -- jilles */
705 if (!mode.join_num)
706 chptr->join_count = chptr->join_delta = 0;
707 }
708
709 set_final_mode(&mode, oldmode);
710 chptr->mode = mode;
711
712 /* Lost the TS, other side wins, so remove modes on this side */
713 if(!keep_our_modes)
714 {
715 remove_our_modes(chptr, fakesource_p);
716 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
717 {
718 del_invite(chptr, ptr->data);
719 }
730c5ff1
JT
720
721 if(rb_dlink_list_length(&chptr->banlist) > 0)
722 remove_ban_list(chptr, fakesource_p, &chptr->banlist, 'b', ALL_MEMBERS);
723 if(rb_dlink_list_length(&chptr->exceptlist) > 0)
724 remove_ban_list(chptr, fakesource_p, &chptr->exceptlist,
725 'e', ONLY_CHANOPS);
726 if(rb_dlink_list_length(&chptr->invexlist) > 0)
727 remove_ban_list(chptr, fakesource_p, &chptr->invexlist,
728 'I', ONLY_CHANOPS);
729 if(rb_dlink_list_length(&chptr->quietlist) > 0)
730 remove_ban_list(chptr, fakesource_p, &chptr->quietlist,
731 'q', ALL_MEMBERS);
732 chptr->bants++;
733
452382d0
VY
734 sendto_channel_local(ALL_MEMBERS, chptr,
735 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
736 me.name, chptr->chname, chptr->chname,
737 (long) oldts, (long) newts);
738 /* Update capitalization in channel name, this makes the
739 * capitalization timestamped like modes are -- jilles */
740 strcpy(chptr->chname, parv[2]);
741 }
742
743 if(*modebuf != '\0')
744 sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
745 fakesource_p->name, chptr->chname, modebuf, parabuf);
746
747 *modebuf = *parabuf = '\0';
748
749 if(parv[3][0] != '0' && keep_new_modes)
750 modes = channel_modes(chptr, source_p);
751 else
752 modes = empty_modes;
753
452382d0
VY
754 mlen_uid = rb_sprintf(buf_uid, ":%s SJOIN %ld %s %s :",
755 use_id(source_p), (long) chptr->channelts, parv[2], modes);
756 ptr_uid = buf_uid + mlen_uid;
757
758 mbuf = modebuf;
759 para[0] = para[1] = para[2] = para[3] = empty;
760 pargs = 0;
761 len_nick = len_uid = 0;
762
763 /* if theres a space, theres going to be more than one nick, change the
764 * first space to \0, so s is just the first nick, and point p to the
765 * second nick
766 */
767 if((p = strchr(s, ' ')) != NULL)
768 {
769 *p++ = '\0';
770 }
771
772 *mbuf++ = '+';
773
774 while (s)
775 {
776 fl = 0;
777
778 for (i = 0; i < 2; i++)
779 {
780 if(*s == '@')
781 {
782 fl |= CHFL_CHANOP;
783 s++;
784 }
785 else if(*s == '+')
786 {
787 fl |= CHFL_VOICE;
788 s++;
789 }
790 }
791
792 /* if the client doesnt exist or is fake direction, skip. */
793 if(!(target_p = find_client(s)) ||
794 (target_p->from != client_p) || !IsPerson(target_p))
795 goto nextnick;
796
797 /* we assume for these we can fit at least one nick/uid in.. */
798
799 /* check we can fit another status+nick+space into a buffer */
452382d0
VY
800 if((mlen_uid + len_uid + IDLEN + 3) > (BUFSIZE - 3))
801 {
802 *(ptr_uid - 1) = '\0';
803 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
804 ptr_uid = buf_uid + mlen_uid;
805 len_uid = 0;
806 }
807
808 if(keep_new_modes)
809 {
810 if(fl & CHFL_CHANOP)
811 {
452382d0
VY
812 *ptr_uid++ = '@';
813 len_nick++;
814 len_uid++;
815 }
816 if(fl & CHFL_VOICE)
817 {
452382d0
VY
818 *ptr_uid++ = '+';
819 len_nick++;
820 len_uid++;
821 }
822 }
823
824 /* copy the nick to the two buffers */
452382d0
VY
825 len = rb_sprintf(ptr_uid, "%s ", use_id(target_p));
826 ptr_uid += len;
827 len_uid += len;
828
829 if(!keep_new_modes)
830 fl = 0;
831
832 if(!IsMember(target_p, chptr))
833 {
834 add_user_to_channel(chptr, target_p, fl);
835 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
836 target_p->name,
837 target_p->username, target_p->host, parv[2]);
838 joins++;
839 }
840
841 if(fl & CHFL_CHANOP)
842 {
843 *mbuf++ = 'o';
844 para[pargs++] = target_p->name;
845
846 /* a +ov user.. bleh */
847 if(fl & CHFL_VOICE)
848 {
849 /* its possible the +o has filled up MAXMODEPARAMS, if so, start
850 * a new buffer
851 */
852 if(pargs >= MAXMODEPARAMS)
853 {
854 *mbuf = '\0';
855 sendto_channel_local(ALL_MEMBERS, chptr,
856 ":%s MODE %s %s %s %s %s %s",
857 fakesource_p->name, chptr->chname,
858 modebuf,
859 para[0], para[1], para[2], para[3]);
860 mbuf = modebuf;
861 *mbuf++ = '+';
862 para[0] = para[1] = para[2] = para[3] = NULL;
863 pargs = 0;
864 }
865
866 *mbuf++ = 'v';
867 para[pargs++] = target_p->name;
868 }
869 }
870 else if(fl & CHFL_VOICE)
871 {
872 *mbuf++ = 'v';
873 para[pargs++] = target_p->name;
874 }
875
876 if(pargs >= MAXMODEPARAMS)
877 {
878 *mbuf = '\0';
879 sendto_channel_local(ALL_MEMBERS, chptr,
880 ":%s MODE %s %s %s %s %s %s",
881 fakesource_p->name,
882 chptr->chname,
883 modebuf, para[0], para[1], para[2], para[3]);
884 mbuf = modebuf;
885 *mbuf++ = '+';
886 para[0] = para[1] = para[2] = para[3] = NULL;
887 pargs = 0;
888 }
889
890 nextnick:
891 /* p points to the next nick */
892 s = p;
893
894 /* if there was a trailing space and p was pointing to it, then we
895 * need to exit.. this has the side effect of breaking double spaces
896 * in an sjoin.. but that shouldnt happen anyway
897 */
898 if(s && (*s == '\0'))
899 s = p = NULL;
900
901 /* if p was NULL due to no spaces, s wont exist due to the above, so
902 * we cant check it for spaces.. if there are no spaces, then when
903 * we next get here, s will be NULL
904 */
905 if(s && ((p = strchr(s, ' ')) != NULL))
906 {
907 *p++ = '\0';
908 }
909 }
910
911 *mbuf = '\0';
912 if(pargs)
913 {
914 sendto_channel_local(ALL_MEMBERS, chptr,
915 ":%s MODE %s %s %s %s %s %s",
916 fakesource_p->name, chptr->chname, modebuf,
917 para[0], CheckEmpty(para[1]),
918 CheckEmpty(para[2]), CheckEmpty(para[3]));
919 }
920
921 if(!joins && !(chptr->mode.mode & MODE_PERMANENT) && isnew)
922 {
923 destroy_channel(chptr);
924
925 return 0;
926 }
927
928 /* Keep the colon if we're sending an SJOIN without nicks -- jilles */
929 if (joins)
930 {
452382d0
VY
931 *(ptr_uid - 1) = '\0';
932 }
933
934 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
452382d0 935
452382d0
VY
936 return 0;
937}
938
f4a80ce6 939/*
940 * do_join_0
941 *
942 * inputs - pointer to client doing join 0
943 * output - NONE
944 * side effects - Use has decided to join 0. This is legacy
945 * from the days when channels were numbers not names. *sigh*
946 * There is a bunch of evilness necessary here due to
947 * anti spambot code.
948 */
949static void
950do_join_0(struct Client *client_p, struct Client *source_p)
951{
952 struct membership *msptr;
953 struct Channel *chptr = NULL;
08d11e34 954 rb_dlink_node *ptr;
f4a80ce6 955
956 /* Finish the flood grace period... */
957 if(MyClient(source_p) && !IsFloodDone(source_p))
958 flood_endgrace(source_p);
959
f4a80ce6 960 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s JOIN 0", use_id(source_p));
f4a80ce6 961
962 if(source_p->user->channel.head && MyConnect(source_p) &&
963 !IsOper(source_p) && !IsExemptSpambot(source_p))
964 check_spambot_warning(source_p, NULL);
965
966 while((ptr = source_p->user->channel.head))
967 {
968 msptr = ptr->data;
969 chptr = msptr->chptr;
970 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
971 source_p->name,
972 source_p->username, source_p->host, chptr->chname);
973 remove_user_from_channel(msptr);
974 }
975}
976
212380e3 977static int
978check_channel_name_loc(struct Client *source_p, const char *name)
979{
dea418e9
JT
980 const char *p;
981
212380e3 982 s_assert(name != NULL);
983 if(EmptyString(name))
984 return 0;
985
986 if(ConfigFileEntry.disable_fake_channels && !IsOper(source_p))
987 {
dea418e9 988 for(p = name; *p; ++p)
212380e3 989 {
dea418e9 990 if(!IsChanChar(*p) || IsFakeChanChar(*p))
212380e3 991 return 0;
992 }
993 }
994 else
995 {
dea418e9 996 for(p = name; *p; ++p)
212380e3 997 {
dea418e9 998 if(!IsChanChar(*p))
212380e3 999 return 0;
1000 }
1001 }
1002
dea418e9
JT
1003 if(ConfigChannel.only_ascii_channels)
1004 {
1005 for(p = name; *p; ++p)
1006 if(*p < 33 || *p > 126)
1007 return 0;
1008 }
1009
212380e3 1010 return 1;
1011}
1012
212380e3 1013static void
1014set_final_mode(struct Mode *mode, struct Mode *oldmode)
1015{
1016 int dir = MODE_QUERY;
1017 char *pbuf = parabuf;
1018 int len;
1019 int i;
1020
1021 /* ok, first get a list of modes we need to add */
75818939 1022 for (i = 0; i < 256; i++)
212380e3 1023 {
75818939 1024 if((mode->mode & chmode_flags[i]) && !(oldmode->mode & chmode_flags[i]))
212380e3 1025 {
1026 if(dir != MODE_ADD)
1027 {
1028 *mbuf++ = '+';
1029 dir = MODE_ADD;
1030 }
75818939 1031 *mbuf++ = i;
212380e3 1032 }
1033 }
1034
1035 /* now the ones we need to remove. */
75818939 1036 for (i = 0; i < 256; i++)
212380e3 1037 {
75818939 1038 if((oldmode->mode & chmode_flags[i]) && !(mode->mode & chmode_flags[i]))
212380e3 1039 {
1040 if(dir != MODE_DEL)
1041 {
1042 *mbuf++ = '-';
1043 dir = MODE_DEL;
1044 }
75818939 1045 *mbuf++ = i;
212380e3 1046 }
1047 }
1048
1049 if(oldmode->limit && !mode->limit)
1050 {
1051 if(dir != MODE_DEL)
1052 {
1053 *mbuf++ = '-';
1054 dir = MODE_DEL;
1055 }
1056 *mbuf++ = 'l';
1057 }
1058 if(oldmode->key[0] && !mode->key[0])
1059 {
1060 if(dir != MODE_DEL)
1061 {
1062 *mbuf++ = '-';
1063 dir = MODE_DEL;
1064 }
1065 *mbuf++ = 'k';
581fa5c4 1066 len = rb_sprintf(pbuf, "%s ", oldmode->key);
212380e3 1067 pbuf += len;
1068 }
1069 if(oldmode->join_num && !mode->join_num)
1070 {
1071 if(dir != MODE_DEL)
1072 {
1073 *mbuf++ = '-';
1074 dir = MODE_DEL;
1075 }
1076 *mbuf++ = 'j';
1077 }
1078 if(oldmode->forward[0] && !mode->forward[0])
1079 {
1080 if(dir != MODE_DEL)
1081 {
1082 *mbuf++ = '-';
1083 dir = MODE_DEL;
1084 }
1085 *mbuf++ = 'f';
1086 }
1087 if(mode->limit && oldmode->limit != mode->limit)
1088 {
1089 if(dir != MODE_ADD)
1090 {
1091 *mbuf++ = '+';
1092 dir = MODE_ADD;
1093 }
1094 *mbuf++ = 'l';
581fa5c4 1095 len = rb_sprintf(pbuf, "%d ", mode->limit);
212380e3 1096 pbuf += len;
1097 }
1098 if(mode->key[0] && strcmp(oldmode->key, mode->key))
1099 {
1100 if(dir != MODE_ADD)
1101 {
1102 *mbuf++ = '+';
1103 dir = MODE_ADD;
1104 }
1105 *mbuf++ = 'k';
581fa5c4 1106 len = rb_sprintf(pbuf, "%s ", mode->key);
212380e3 1107 pbuf += len;
1108 }
1109 if(mode->join_num && (oldmode->join_num != mode->join_num || oldmode->join_time != mode->join_time))
1110 {
1111 if(dir != MODE_ADD)
1112 {
1113 *mbuf++ = '+';
1114 dir = MODE_ADD;
1115 }
1116 *mbuf++ = 'j';
581fa5c4 1117 len = rb_sprintf(pbuf, "%d:%d ", mode->join_num, mode->join_time);
212380e3 1118 pbuf += len;
1119 }
1120 if(mode->forward[0] && strcmp(oldmode->forward, mode->forward) && ConfigChannel.use_forward)
1121 {
1122 if(dir != MODE_ADD)
1123 {
1124 *mbuf++ = '+';
1125 dir = MODE_ADD;
1126 }
1127 *mbuf++ = 'f';
581fa5c4 1128 len = rb_sprintf(pbuf, "%s ", mode->forward);
212380e3 1129 pbuf += len;
1130 }
1131 *mbuf = '\0';
1132}
1133
1134/*
1135 * remove_our_modes
1136 *
1137 * inputs -
1138 * output -
1139 * side effects -
1140 */
1141static void
1142remove_our_modes(struct Channel *chptr, struct Client *source_p)
1143{
1144 struct membership *msptr;
08d11e34 1145 rb_dlink_node *ptr;
212380e3 1146 char lmodebuf[MODEBUFLEN];
1147 char *lpara[MAXMODEPARAMS];
1148 int count = 0;
1149 int i;
1150
1151 mbuf = lmodebuf;
1152 *mbuf++ = '-';
1153
1154 for(i = 0; i < MAXMODEPARAMS; i++)
1155 lpara[i] = NULL;
1156
08d11e34 1157 RB_DLINK_FOREACH(ptr, chptr->members.head)
212380e3 1158 {
1159 msptr = ptr->data;
1160
1161 if(is_chanop(msptr))
1162 {
1163 msptr->flags &= ~CHFL_CHANOP;
1164 lpara[count++] = msptr->client_p->name;
1165 *mbuf++ = 'o';
1166
1167 /* +ov, might not fit so check. */
1168 if(is_voiced(msptr))
1169 {
1170 if(count >= MAXMODEPARAMS)
1171 {
1172 *mbuf = '\0';
1173 sendto_channel_local(ALL_MEMBERS, chptr,
1174 ":%s MODE %s %s %s %s %s %s",
e6a0717d 1175 source_p->name, chptr->chname,
212380e3 1176 lmodebuf, lpara[0], lpara[1],
1177 lpara[2], lpara[3]);
1178
1179 /* preserve the initial '-' */
1180 mbuf = lmodebuf;
1181 *mbuf++ = '-';
1182 count = 0;
1183
1184 for(i = 0; i < MAXMODEPARAMS; i++)
1185 lpara[i] = NULL;
1186 }
1187
1188 msptr->flags &= ~CHFL_VOICE;
1189 lpara[count++] = msptr->client_p->name;
1190 *mbuf++ = 'v';
1191 }
1192 }
1193 else if(is_voiced(msptr))
1194 {
1195 msptr->flags &= ~CHFL_VOICE;
1196 lpara[count++] = msptr->client_p->name;
1197 *mbuf++ = 'v';
1198 }
1199 else
1200 continue;
1201
1202 if(count >= MAXMODEPARAMS)
1203 {
1204 *mbuf = '\0';
1205 sendto_channel_local(ALL_MEMBERS, chptr,
1206 ":%s MODE %s %s %s %s %s %s",
e6a0717d 1207 source_p->name, chptr->chname, lmodebuf,
212380e3 1208 lpara[0], lpara[1], lpara[2], lpara[3]);
1209 mbuf = lmodebuf;
1210 *mbuf++ = '-';
1211 count = 0;
1212
1213 for(i = 0; i < MAXMODEPARAMS; i++)
1214 lpara[i] = NULL;
1215 }
1216 }
1217
1218 if(count != 0)
1219 {
1220 *mbuf = '\0';
1221 sendto_channel_local(ALL_MEMBERS, chptr,
1222 ":%s MODE %s %s %s %s %s %s",
e6a0717d 1223 source_p->name, chptr->chname, lmodebuf,
212380e3 1224 EmptyString(lpara[0]) ? "" : lpara[0],
1225 EmptyString(lpara[1]) ? "" : lpara[1],
1226 EmptyString(lpara[2]) ? "" : lpara[2],
1227 EmptyString(lpara[3]) ? "" : lpara[3]);
1228
1229 }
1230}
452382d0
VY
1231
1232/* remove_ban_list()
1233 *
1234 * inputs - channel, source, list to remove, char of mode, caps needed
1235 * outputs -
1236 * side effects - given list is removed, with modes issued to local clients
452382d0
VY
1237 */
1238static void
1239remove_ban_list(struct Channel *chptr, struct Client *source_p,
0a70e150 1240 rb_dlink_list * list, char c, int mems)
452382d0
VY
1241{
1242 static char lmodebuf[BUFSIZE];
1243 static char lparabuf[BUFSIZE];
1244 struct Ban *banptr;
1245 rb_dlink_node *ptr;
1246 rb_dlink_node *next_ptr;
1247 char *pbuf;
1248 int count = 0;
1249 int cur_len, mlen, plen;
1250
1251 pbuf = lparabuf;
1252
1253 cur_len = mlen = rb_sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
1254 mbuf = lmodebuf + mlen;
1255
1256 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
1257 {
1258 banptr = ptr->data;
1259
1260 /* trailing space, and the mode letter itself */
1261 plen = strlen(banptr->banstr) + 2;
1262
1263 if(count >= MAXMODEPARAMS || (cur_len + plen) > BUFSIZE - 4)
1264 {
1265 /* remove trailing space */
1266 *mbuf = '\0';
1267 *(pbuf - 1) = '\0';
1268
1269 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
452382d0
VY
1270
1271 cur_len = mlen;
1272 mbuf = lmodebuf + mlen;
1273 pbuf = lparabuf;
1274 count = 0;
1275 }
1276
1277 *mbuf++ = c;
1278 cur_len += plen;
1279 pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr);
1280 count++;
1281
1282 free_ban(banptr);
1283 }
1284
1285 *mbuf = '\0';
1286 *(pbuf - 1) = '\0';
1287 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
452382d0
VY
1288
1289 list->head = list->tail = NULL;
1290 list->length = 0;
1291}