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