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