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