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