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