2 * IRC - Internet Relay Chat, ircd/channel.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Co Center
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 1, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
46 #include "sprintf_irc.h"
47 #include "querycmds.h"
51 aChannel *channel = NullChn;
53 static void sendmodeto_one(aClient *cptr, char *from, char *name,
54 char *mode, char *param, time_t creationtime);
55 static void add_invite(aClient *, aChannel *);
56 static int add_banid(aClient *, aChannel *, char *, int, int);
57 static Link *next_overlapped_ban(void);
58 static Link *next_removed_overlapped_ban(void);
59 static int can_join(aClient *, aChannel *, char *);
60 static void channel_modes(aClient *, char *, char *, aChannel *);
61 static int del_banid(aChannel *, char *, int);
62 static int is_banned(aClient *, aChannel *, Link *);
63 static int number_of_zombies(aChannel *);
64 static int is_deopped(aClient *, aChannel *);
65 static int set_mode(aClient *, aClient *, aChannel *, int,
66 char **, char *, char *, char *, int *);
67 static void sub1_from_channel(aChannel *);
68 static void send_hack_notice(aClient *, aClient *, int, char *[], int, int);
69 static void clean_channelname(char *);
71 void del_invite(aClient *, aChannel *);
73 static char *PartFmt1 = ":%s PART %s";
74 static char *PartFmt2 = ":%s PART %s :%s";
76 * some buffers for rebuilding channel/nick lists with ,'s
78 static char nickbuf[BUFSIZE], buf[BUFSIZE];
79 static char modebuf[MODEBUFLEN], parabuf[MODEBUFLEN];
80 static char nparabuf[MODEBUFLEN];
83 * Maximum acceptable lag time in seconds: A channel younger than
84 * this is not protected against hacking admins.
85 * Mainly here to check if the TS clocks really sync (otherwise this
86 * will start causing HACK notices.
87 * This value must be the same on all servers.
89 * This value has been increased to 1 day in order to distinguish this
90 * "normal" type of HACK wallops / desyncs, from possiblity still
93 #define TS_LAG_TIME ((time_t)86400)
96 * A Magic TS that is used for channels that are created by JOIN,
97 * a channel with this TS accepts all TS without complaining that
98 * it might receive later via MODE or CREATE.
100 #define MAGIC_REMOTE_JOIN_TS 1270080000
103 * Use a global variable to remember if an oper set a mode on a local channel. Ugly,
104 * but the only way to do it without changing set_mode intensively.
106 int LocalChanOperMode = 0;
109 * return the length (>=0) of a chain of links.
111 static int list_length(Link *lp)
115 for (; lp; lp = lp->next)
123 * Find the client structure for a nick name (user) using history
124 * mechanism if necessary. If the client is not found, an error
125 * message (NO SUCH NICK) is generated. If the client was found
126 * through the history, chasing will be 1 and otherwise 0.
128 static aClient *find_chasing(aClient *sptr, char *user, int *chasing)
130 Reg2 aClient *who = FindClient(user);
136 if (!(who = get_history(user, (long)KILLCHASETIMELIMIT)))
138 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, sptr->name, user);
147 * Create a string of form "foo!bar@fubar" given foo, bar and fubar
148 * as the parameters. If NULL, they become "*".
150 static char *make_nick_user_host(char *nick, char *name, char *host)
152 static char namebuf[NICKLEN + USERLEN + HOSTLEN + 3];
153 sprintf_irc(namebuf, "%s!%s@%s", nick, name, host);
158 * Create a string of form "foo!bar@123.456.789.123" given foo, bar and the
159 * IP-number as the parameters. If NULL, they become "*".
161 static char *make_nick_user_ip(char *nick, char *name, struct in_addr ip)
163 static char ipbuf[NICKLEN + USERLEN + 16 + 3];
164 sprintf_irc(ipbuf, "%s!%s@%s", nick, name, inetntoa(ip));
171 * `cptr' must be the client adding the ban.
173 * If `change' is true then add `banid' to channel `chptr'.
174 * Returns 0 if the ban was added.
175 * Returns -2 if the ban already existed and was marked CHFL_BURST_BAN_WIPEOUT.
176 * Return -1 otherwise.
178 * Those bans that overlapped with `banid' are flagged with CHFL_BAN_OVERLAPPED
179 * when `change' is false, otherwise they will be removed from the banlist.
180 * Subsequently calls to next_overlapped_ban() or next_removed_overlapped_ban()
181 * respectively will return these bans until NULL is returned.
183 * If `firsttime' is true, the ban list as returned by next_overlapped_ban()
184 * is reset (unless a non-zero value is returned, in which case the
185 * CHFL_BAN_OVERLAPPED flag might not have been reset!).
189 static Link *next_ban, *prev_ban, *removed_bans_list;
191 static int add_banid(aClient *cptr, aChannel *chptr, char *banid,
192 int change, int firsttime)
194 Reg1 Link *ban, **banp;
195 Reg2 int cnt = 0, removed_bans = 0, len = strlen(banid);
200 if (prev_ban || removed_bans_list)
201 MyCoreDump; /* Memory leak */
205 for (banp = &chptr->banlist; *banp;)
207 len += strlen((*banp)->value.ban.banstr);
209 if (((*banp)->flags & CHFL_BURST_BAN_WIPEOUT))
211 if (!strcmp((*banp)->value.ban.banstr, banid))
213 (*banp)->flags &= ~CHFL_BURST_BAN_WIPEOUT;
217 else if (!mmatch((*banp)->value.ban.banstr, banid))
219 if (!mmatch(banid, (*banp)->value.ban.banstr))
227 len -= strlen(tmp->value.ban.banstr);
231 /* Silently remove overlapping bans */
232 RunFree(tmp->value.ban.banstr);
233 RunFree(tmp->value.ban.who);
236 /* These will be sent to the user later as -b */
237 tmp->next = removed_bans_list;
238 removed_bans_list = tmp;
242 else if (!(tmp->flags & CHFL_BURST_BAN_WIPEOUT))
244 tmp->flags |= CHFL_BAN_OVERLAPPED;
255 (*banp)->flags &= ~CHFL_BAN_OVERLAPPED;
256 banp = &(*banp)->next;
259 if (MyUser(cptr) && !removed_bans && (len > MAXBANLENGTH || (cnt >= MAXBANS)))
261 sendto_one(cptr, err_str(ERR_BANLISTFULL), me.name, cptr->name,
262 chptr->chname, banid);
269 ban->next = chptr->banlist;
270 ban->value.ban.banstr = (char *)RunMalloc(strlen(banid) + 1);
271 strcpy(ban->value.ban.banstr, banid);
272 ban->value.ban.who = (char *)RunMalloc(strlen(cptr->name) + 1);
273 strcpy(ban->value.ban.who, cptr->name);
274 ban->value.ban.when = now;
275 ban->flags = CHFL_BAN; /* This bit is never used I think... */
276 if ((ip_start = strrchr(banid, '@')) && check_if_ipmask(ip_start + 1))
277 ban->flags |= CHFL_BAN_IPMASK;
278 chptr->banlist = ban;
279 /* Erase ban-valid-bit */
280 for (ban = chptr->members; ban; ban = ban->next)
281 ban->flags &= ~CHFL_BANVALID; /* `ban' == channel member ! */
286 static Link *next_overlapped_ban(void)
288 Reg1 Link *tmp = next_ban;
292 for (ban = tmp->next; ban; ban = ban->next)
293 if ((ban->flags & CHFL_BAN_OVERLAPPED))
300 static Link *next_removed_overlapped_ban(void)
302 Reg1 Link *tmp = removed_bans_list;
305 if (prev_ban->value.ban.banstr) /* Can be set to NULL in set_mode() */
306 RunFree(prev_ban->value.ban.banstr);
307 RunFree(prev_ban->value.ban.who);
311 removed_bans_list = removed_bans_list->next;
319 * If `change' is true, delete `banid' from channel `chptr'.
320 * Returns `false' if removal was (or would have been) successful.
322 static int del_banid(aChannel *chptr, char *banid, int change)
329 for (ban = &(chptr->banlist); *ban; ban = &((*ban)->next))
330 if (strCasediff(banid, (*ban)->value.ban.banstr) == 0)
336 RunFree(tmp->value.ban.banstr);
337 RunFree(tmp->value.ban.who);
339 /* Erase ban-valid-bit, for channel members that are banned */
340 for (tmp = chptr->members; tmp; tmp = tmp->next)
341 if ((tmp->flags & (CHFL_BANNED | CHFL_BANVALID)) ==
342 (CHFL_BANNED | CHFL_BANVALID))
343 tmp->flags &= ~CHFL_BANVALID; /* `tmp' == channel member */
351 * IsMember - returns Link * if a person is joined and not a zombie
353 Link *IsMember(aClient *cptr, aChannel *chptr)
356 return (((lp = find_user_link(chptr->members, cptr)) &&
357 !(lp->flags & CHFL_ZOMBIE)) ? lp : NULL);
361 * is_banned - a non-zero value if banned else 0.
363 static int is_banned(aClient *cptr, aChannel *chptr, Link *member)
366 char *s, *ip_s = NULL;
373 if ((member->flags & CHFL_BANVALID))
374 return (member->flags & CHFL_BANNED);
377 s = make_nick_user_host(cptr->name, cptr->user->username, cptr->user->host);
379 for (tmp = chptr->banlist; tmp; tmp = tmp->next)
381 if ((tmp->flags & CHFL_BAN_IPMASK))
384 ip_s = make_nick_user_ip(cptr->name, cptr->user->username, cptr->ip);
385 if (match(tmp->value.ban.banstr, ip_s) == 0)
388 else if (match(tmp->value.ban.banstr, s) == 0)
394 member->flags |= CHFL_BANVALID;
397 member->flags |= CHFL_BANNED;
402 member->flags &= ~CHFL_BANNED;
407 return (tmp != NULL);
411 * adds a user to a channel by adding another link to the channels member
414 static void add_user_to_channel(aChannel *chptr, aClient *who, int flags)
421 ptr->value.cptr = who;
423 ptr->next = chptr->members;
424 chptr->members = ptr;
428 ptr->value.chptr = chptr;
429 ptr->next = who->user->channel;
430 who->user->channel = ptr;
435 void remove_user_from_channel(aClient *sptr, aChannel *chptr)
439 Reg3 Link *lp = chptr->members;
441 for (; lp && (lp->flags & CHFL_ZOMBIE || lp->value.cptr == sptr);
445 for (curr = &chptr->members; (tmp = *curr); curr = &tmp->next)
446 if (tmp->value.cptr == sptr)
452 for (curr = &sptr->user->channel; (tmp = *curr); curr = &tmp->next)
453 if (tmp->value.chptr == chptr)
459 sptr->user->joined--;
463 sptr = chptr->members->value.cptr;
466 sub1_from_channel(chptr);
468 sub1_from_channel(chptr);
471 int is_chan_op(aClient *cptr, aChannel *chptr)
476 if ((lp = find_user_link(chptr->members, cptr)) &&
477 !(lp->flags & CHFL_ZOMBIE))
478 return (lp->flags & CHFL_CHANOP);
483 static int is_deopped(aClient *cptr, aChannel *chptr)
488 if ((lp = find_user_link(chptr->members, cptr)))
489 return (lp->flags & CHFL_DEOPPED);
491 return (IsUser(cptr) ? 1 : 0);
494 int is_zombie(aClient *cptr, aChannel *chptr)
499 if ((lp = find_user_link(chptr->members, cptr)))
500 return (lp->flags & CHFL_ZOMBIE);
505 int has_voice(aClient *cptr, aChannel *chptr)
510 if ((lp = find_user_link(chptr->members, cptr)) &&
511 !(lp->flags & CHFL_ZOMBIE))
512 return (lp->flags & CHFL_VOICE);
517 int can_send(aClient *cptr, aChannel *chptr)
521 lp = IsMember(cptr, chptr);
523 if ((!lp || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE)) ||
524 (lp->flags & CHFL_ZOMBIE)) && MyUser(cptr) && is_banned(cptr, chptr, lp))
527 if (chptr->mode.mode & MODE_MODERATED &&
528 (!lp || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE)) ||
529 (lp->flags & CHFL_ZOMBIE)))
530 return (MODE_MODERATED);
532 if (!lp && ((chptr->mode.mode & MODE_NOPRIVMSGS) ||
533 IsModelessChannel(chptr->chname)))
534 return (MODE_NOPRIVMSGS);
540 * write the "simple" list of channel modes for channel chptr onto buffer mbuf
541 * with the parameters in pbuf.
543 static void channel_modes(aClient *cptr, char *mbuf, char *pbuf,
547 if (chptr->mode.mode & MODE_SECRET)
549 else if (chptr->mode.mode & MODE_PRIVATE)
551 if (chptr->mode.mode & MODE_MODERATED)
553 if (chptr->mode.mode & MODE_TOPICLIMIT)
555 if (chptr->mode.mode & MODE_INVITEONLY)
557 if (chptr->mode.mode & MODE_NOPRIVMSGS)
559 if (chptr->mode.limit)
562 sprintf_irc(pbuf, "%d", chptr->mode.limit);
564 if (*chptr->mode.key)
567 if (is_chan_op(cptr, chptr) || IsServer(cptr))
569 if (chptr->mode.limit)
571 strcat(pbuf, chptr->mode.key);
578 static int send_mode_list(aClient *cptr, char *chname, time_t creationtime,
579 Link *top, int mask, char flag)
582 Reg2 char *cp, *name;
583 int count = 0, send = 0, sent = 0;
585 cp = modebuf + strlen(modebuf);
586 if (*parabuf) /* mode +l or +k xx */
588 for (lp = top; lp; lp = lp->next)
590 if (!(lp->flags & mask))
592 if (mask == CHFL_BAN)
593 name = lp->value.ban.banstr;
595 name = lp->value.cptr->name;
596 if (strlen(parabuf) + strlen(name) + 11 < (size_t)MODEBUFLEN)
598 strcat(parabuf, " ");
599 strcat(parabuf, name);
610 /* cptr is always a server! So we send creationtimes */
611 sendmodeto_one(cptr, me.name, chname, modebuf, parabuf, creationtime);
619 strcpy(parabuf, name);
630 * send "cptr" a full list of the modes for channel chptr.
632 void send_channel_modes(aClient *cptr, aChannel *chptr)
635 if (IsLocalChannel(chptr->chname))
638 *modebuf = *parabuf = '\0';
639 channel_modes(cptr, modebuf, parabuf, chptr);
641 if (Protocol(cptr) < 10)
643 sent = send_mode_list(cptr, chptr->chname, chptr->creationtime,
644 chptr->members, CHFL_CHANOP, 'o');
645 if (!sent && chptr->creationtime)
646 sendto_one(cptr, ":%s MODE %s %s %s " TIME_T_FMT, me.name,
647 chptr->chname, modebuf, parabuf, chptr->creationtime);
648 else if (modebuf[1] || *parabuf)
649 sendmodeto_one(cptr, me.name,
650 chptr->chname, modebuf, parabuf, chptr->creationtime);
655 send_mode_list(cptr, chptr->chname, chptr->creationtime,
656 chptr->banlist, CHFL_BAN, 'b');
657 if (modebuf[1] || *parabuf)
658 sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
659 parabuf, chptr->creationtime);
664 send_mode_list(cptr, chptr->chname, chptr->creationtime,
665 chptr->members, CHFL_VOICE, 'v');
666 if (modebuf[1] || *parabuf)
667 sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
668 parabuf, chptr->creationtime);
672 static unsigned int current_flags[4] =
673 { 0, CHFL_CHANOP | CHFL_VOICE, CHFL_VOICE, CHFL_CHANOP };
674 int first = 1, full = 1, flag_cnt = 0, new_mode = 0;
676 Link *lp1 = chptr->members;
677 Link *lp2 = chptr->banlist;
678 for (first = 1; full; first = 0) /* Loop for multiple messages */
680 full = 0; /* Assume by default we get it
681 all in one message */
683 /* (Continued) prefix: "<Y> BURST <channel> <TS>" */
684 sprintf_irc(sendbuf, "%s BURST %s " TIME_T_FMT, NumServ(&me),
685 chptr->chname, chptr->creationtime);
686 sblen = strlen(sendbuf);
688 if (first && modebuf[1]) /* Add simple modes (iklmnpst)
691 /* prefix: "<Y> BURST <channel> <TS>[ <modes>[ <params>]]" */
692 sendbuf[sblen++] = ' ';
693 strcpy(sendbuf + sblen, modebuf);
694 sblen += strlen(modebuf);
697 sendbuf[sblen++] = ' ';
698 strcpy(sendbuf + sblen, parabuf);
699 sblen += strlen(parabuf);
703 /* Attach nicks, comma seperated " nick[:modes],nick[:modes],..." */
704 /* Run 4 times over all members, to group the members with the
705 * same mode together */
706 for (first = 1; flag_cnt < 4;
707 lp1 = chptr->members, new_mode = 1, flag_cnt++)
709 for (; lp1; lp1 = lp1->next)
711 if ((lp1->flags & (CHFL_CHANOP | CHFL_VOICE)) !=
712 current_flags[flag_cnt])
713 continue; /* Skip members with different flags */
714 if (sblen + NUMNICKLEN + 4 > BUFSIZE - 3)
715 /* The 4 is a possible ",:ov"
716 The -3 is for the "\r\n\0" that is added in send.c */
718 full = 1; /* Make sure we continue after
720 break; /* Do not add this member to this message */
722 sendbuf[sblen++] = first ? ' ' : ',';
723 first = 0; /* From now on, us comma's to add new nicks */
725 sprintf_irc(sendbuf + sblen, "%s%s", NumNick(lp1->value.cptr));
726 sblen += strlen(sendbuf + sblen);
728 if (new_mode) /* Do we have a nick with a new mode ? */
731 if (lp1->flags & (CHFL_CHANOP | CHFL_VOICE)) {
732 sendbuf[sblen++] = ':';
733 if (lp1->flags & CHFL_CHANOP)
734 sendbuf[sblen++] = 'o';
735 if (lp1->flags & CHFL_VOICE)
736 sendbuf[sblen++] = 'v';
746 /* Attach all bans, space seperated " :%ban ban ..." */
747 for (first = 2; lp2; lp2 = lp2->next)
749 len = strlen(lp2->value.ban.banstr);
750 if (sblen + len + 1 + first > BUFSIZE - 3)
751 /* The +1 stands for the added ' '.
752 * The +first stands for the added ":%".
753 * The -3 is for the "\r\n\0" that is added in send.c
762 sendbuf[sblen++] = ' ';
763 sendbuf[sblen++] = ':'; /* Will be last parameter */
764 sendbuf[sblen++] = '%'; /* To tell bans apart */
767 sendbuf[sblen++] = ' ';
768 strcpy(sendbuf + sblen, lp2->value.ban.banstr);
773 sendbuf[sblen] = '\0';
774 sendbufto_one(cptr); /* Send this message */
775 } /* Continue when there was something
776 that didn't fit (full==1) */
786 int m_mode(aClient *cptr, aClient *sptr, int parc, char *parv[])
791 /* Now, try to find the channel in question */
794 chptr = FindChannel(parv[1]);
795 if (chptr == NullChn)
796 return m_umode(cptr, sptr, parc, parv);
800 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "MODE");
804 sptr->flags &= ~FLAGS_TS8;
807 clean_channelname(parv[1]);
808 else if (IsLocalChannel(parv[1]))
811 /* sending an error wasnt good, lets just send an empty mode reply.. poptix */
812 if (IsModelessChannel(chptr->chname))
815 sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],
816 chptr->chname, "+nt", "");
822 *modebuf = *parabuf = '\0';
824 channel_modes(sptr, modebuf, parabuf, chptr);
825 sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],
826 chptr->chname, modebuf, parabuf);
827 sendto_one(sptr, rpl_str(RPL_CREATIONTIME), me.name, parv[0],
828 chptr->chname, chptr->creationtime);
832 LocalChanOperMode = 0;
834 if (!(sendts = set_mode(cptr, sptr, chptr, parc - 2, parv + 2,
835 modebuf, parabuf, nparabuf, &badop)))
837 sendto_one(sptr, err_str(IsMember(sptr, chptr) ? ERR_CHANOPRIVSNEEDED :
838 ERR_NOTONCHANNEL), me.name, parv[0], chptr->chname);
843 send_hack_notice(cptr, sptr, parc, parv, badop, 1);
845 if (strlen(modebuf) > (size_t)1 || sendts > 0)
847 if (badop != 2 && strlen(modebuf) > (size_t)1)
849 #ifdef OPER_MODE_LCHAN
850 if (LocalChanOperMode) {
851 sendto_channel_butserv(chptr, &me, ":%s MODE %s %s %s",
852 me.name, chptr->chname, modebuf, parabuf);
853 sendto_op_mask(SNO_HACK4,
854 "OPER MODE: %s MODE %s %s %s",
855 sptr->name,chptr->chname,modebuf,parabuf);
859 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s",
860 parv[0], chptr->chname, modebuf, parabuf);
862 if (IsLocalChannel(chptr->chname))
864 /* We send a creationtime of 0, to mark it as a hack --Run */
865 if (IsServer(sptr) && (badop == 2 || sendts > 0))
867 if (*modebuf == '\0')
868 strcpy(modebuf, "+");
871 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s %s " TIME_T_FMT,
872 parv[0], chptr->chname, modebuf, parabuf,
873 (badop == 4) ? (time_t) 0 : chptr->creationtime);
874 sendto_highprot_butone(cptr, 10, ":%s MODE %s %s %s " TIME_T_FMT,
875 parv[0], chptr->chname, modebuf, nparabuf,
876 (badop == 4) ? (time_t) 0 : chptr->creationtime);
881 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s %s",
882 parv[0], chptr->chname, modebuf, parabuf);
883 sendto_highprot_butone(cptr, 10, ":%s MODE %s %s %s",
884 parv[0], chptr->chname, modebuf, nparabuf);
890 static int DoesOp(char *modebuf)
892 modebuf--; /* Is it possible that a mode
893 starts with o and not +o ? */
895 if (*modebuf == 'o' || *modebuf == 'v')
900 /* This function should be removed when all servers are 2.10 */
901 static void sendmodeto_one(aClient *cptr, char *from, char *name,
902 char *mode, char *param, time_t creationtime)
904 if (IsServer(cptr) && DoesOp(mode) && creationtime)
905 sendto_one(cptr, ":%s MODE %s %s %s " TIME_T_FMT,
906 from, name, mode, param, creationtime);
908 sendto_one(cptr, ":%s MODE %s %s %s", from, name, mode, param);
914 * by Carlo Wood (Run), 05 Oct 1998.
918 * When the nick is longer then NICKLEN, it is cut off (its an error of course).
919 * When the user name or host name are too long (USERLEN and HOSTLEN
920 * respectively) then they are cut off at the start with a '*'.
922 * The following transformations are made:
925 * 2) xxx.xxx -> *!*@host
926 * 3) xxx!yyy -> nick!user@*
927 * 4) xxx@yyy -> *!user@host
928 * 5) xxx!yyy@zzz -> nick!user@host
930 char *pretty_mask(char *mask)
932 static char star[2] = { '*', 0 };
933 char *last_dot = NULL;
936 /* Case 1: default */
941 /* Do a _single_ pass through the characters of the mask: */
942 for (ptr = mask; *ptr; ++ptr)
946 /* Case 3 or 5: Found first '!' (without finding a '@' yet) */
950 else if (*ptr == '@')
952 /* Case 4: Found last '@' (without finding a '!' yet) */
957 else if (*ptr == '.')
959 /* Case 2: Found last '.' (without finding a '!' or '@' yet) */
969 /* Case 4 or 5: Found last '@' */
975 if (user == star && last_dot)
985 char *nick_end = (user != star) ? user - 1 : ptr;
986 if (nick_end - nick > NICKLEN)
992 char *user_end = (host != star) ? host - 1 : ptr;
993 if (user_end - user > USERLEN)
995 user = user_end - USERLEN;
1000 if (host != star && ptr - host > HOSTLEN)
1002 host = ptr - HOSTLEN;
1005 return make_nick_user_host(nick, user, host);
1008 static char bmodebuf[MODEBUFLEN], bparambuf[MODEBUFLEN];
1009 static char nbparambuf[MODEBUFLEN]; /* "Numeric" Bounce Parameter Buffer */
1012 * Check and try to apply the channel modes passed in the parv array for
1013 * the client ccptr to channel chptr. The resultant changes are printed
1014 * into mbuf and pbuf (if any) and applied to the channel.
1016 static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr, int parc,
1017 char *parv[], char *mbuf, char *pbuf, char *npbuf, int *badop)
1019 static Link chops[MAXPARA - 2]; /* This size is only needed when a broken
1020 server sends more then MAXMODEPARAMS
1022 static int flags[] = {
1023 MODE_PRIVATE, 'p', MODE_SECRET, 's',
1024 MODE_MODERATED, 'm', MODE_NOPRIVMSGS, 'n',
1025 MODE_TOPICLIMIT, 't', MODE_INVITEONLY, 'i',
1026 MODE_VOICE, 'v', MODE_KEY, 'k',
1031 Reg2 char *curr = parv[0], *cp = NULL;
1033 Link *member, *tmp = NULL;
1034 unsigned int whatt = MODE_ADD, bwhatt = 0;
1035 int limitset = 0, bounce, add_banid_called = 0;
1036 size_t len, nlen, blen, nblen;
1038 unsigned int nusers = 0, newmode;
1039 int opcnt = 0, banlsent = 0;
1040 int doesdeop = 0, doesop = 0, hacknotice = 0, change, gotts = 0;
1043 static char numeric[16];
1044 char *bmbuf = bmodebuf, *bpbuf = bparambuf, *nbpbuf = nbparambuf;
1045 time_t newtime = (time_t) 0;
1048 *mbuf = *pbuf = *npbuf = *bmbuf = *bpbuf = *nbpbuf = '\0';
1053 mode = &(chptr->mode);
1054 memcpy(&oldm, mode, sizeof(Mode));
1056 * Mode is accepted when sptr is a channel operator
1057 * but also when the mode is received from a server.
1058 * At this point, let any member pass, so they are allowed
1061 if (!(IsServer(cptr) || (tmp = IsMember(sptr, chptr))))
1064 #ifdef OPER_MODE_LCHAN
1065 if (IsOperOnLocalChannel(sptr, chptr->chname) && !(tmp->flags & CHFL_CHANOP))
1066 LocalChanOperMode = 1;
1069 newmode = mode->mode;
1071 while (curr && *curr)
1086 if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1089 * Check for nickname changes and try to follow these
1090 * to make sure the right client is affected by the
1092 * Even if we find a nick with find_chasing() there
1093 * is still a reason to ignore in a special case.
1094 * We need to ignore the mode when:
1095 * - It is part of a net.burst (from a server and
1096 * a MODE_ADD). Ofcourse we don't ignore mode
1097 * changes from Uworld.
1098 * - The found nick is not on the right side off
1100 * This fixes the bug that when someone (tries to)
1101 * ride a net.break and does so with the nick of
1102 * someone on the otherside, that he is nick collided
1103 * (killed) but his +o still ops the other person.
1105 if (MyUser(sptr) || Protocol(cptr) < 10)
1107 if (!(who = find_chasing(sptr, parv[0], NULL)))
1112 if (!(who = findNUser(parv[0])))
1115 if (whatt == MODE_ADD && IsServer(sptr) && who->from != sptr->from &&
1116 !find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))
1118 if (!(member = find_user_link(chptr->members, who)) ||
1119 (MyUser(sptr) && (member->flags & CHFL_ZOMBIE)))
1121 sendto_one(cptr, err_str(ERR_USERNOTINCHANNEL),
1122 me.name, cptr->name, who->name, chptr->chname);
1125 /* if the user is +k, prevent a deop from local user */
1126 if (whatt == MODE_DEL && IsChannelService(who) &&
1127 MyUser(cptr) && *curr == 'o')
1129 sendto_one(cptr, err_str(ERR_ISCHANSERVICE), me.name,
1130 cptr->name, parv[0], chptr->chname);
1133 #ifdef NO_OPER_DEOP_LCHAN
1135 * if the user is an oper on a local channel, prevent him
1136 * from being deoped. that oper can deop himself though.
1138 if (whatt == MODE_DEL && IsOperOnLocalChannel(who, chptr->chname) &&
1139 (who != sptr) && MyUser(cptr) && *curr == 'o')
1141 sendto_one(cptr, err_str(ERR_ISOPERLCHAN), me.name,
1142 cptr->name, parv[0], chptr->chname);
1146 if (whatt == MODE_ADD)
1148 lp = &chops[opcnt++];
1149 lp->value.cptr = who;
1150 if (IsServer(sptr) && (!(who->flags & FLAGS_TS8) || ((*curr == 'o') &&
1151 !(member->flags & (CHFL_SERVOPOK | CHFL_CHANOP)))))
1152 *badop = ((member->flags & CHFL_DEOPPED) && (*curr == 'o')) ? 2 : 3;
1153 lp->flags = (*curr == 'o') ? MODE_CHANOP : MODE_VOICE;
1154 lp->flags |= MODE_ADD;
1156 else if (whatt == MODE_DEL)
1158 lp = &chops[opcnt++];
1159 lp->value.cptr = who;
1160 doesdeop = 1; /* Also when -v */
1161 lp->flags = (*curr == 'o') ? MODE_CHANOP : MODE_VOICE;
1162 lp->flags |= MODE_DEL;
1171 /* check now so we eat the parameter if present */
1176 char *s = &(*parv)[-1];
1177 unsigned short count = KEYLEN + 1;
1179 while (*++s > ' ' && *s != ':' && --count);
1181 if (!**parv) /* nothing left in key */
1184 if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1186 if (whatt == MODE_ADD)
1188 if (*mode->key && !IsServer(cptr))
1189 sendto_one(cptr, err_str(ERR_KEYSET),
1190 me.name, cptr->name, chptr->chname);
1191 else if (!*mode->key || IsServer(cptr))
1193 lp = &chops[opcnt++];
1194 lp->value.cp = *parv;
1195 if (strlen(lp->value.cp) > (size_t)KEYLEN)
1196 lp->value.cp[KEYLEN] = '\0';
1197 lp->flags = MODE_KEY | MODE_ADD;
1201 else if (whatt == MODE_DEL)
1203 if (strCasediff(mode->key, *parv) == 0 || IsServer(cptr))
1205 lp = &chops[opcnt++];
1206 lp->value.cp = mode->key;
1207 lp->flags = MODE_KEY | MODE_DEL;
1215 if (banlsent) /* Only send it once */
1217 for (lp = chptr->banlist; lp; lp = lp->next)
1218 sendto_one(cptr, rpl_str(RPL_BANLIST), me.name, cptr->name,
1219 chptr->chname, lp->value.ban.banstr, lp->value.ban.who,
1220 lp->value.ban.when);
1221 sendto_one(cptr, rpl_str(RPL_ENDOFBANLIST), me.name, cptr->name,
1231 if ((cp = strchr(*parv, ' ')))
1233 if (opcnt >= MAXMODEPARAMS || **parv == ':' || **parv == '\0')
1236 if (whatt == MODE_ADD)
1238 lp = &chops[opcnt++];
1239 lp->value.cp = *parv;
1240 lp->flags = MODE_ADD | MODE_BAN;
1242 else if (whatt == MODE_DEL)
1244 lp = &chops[opcnt++];
1245 lp->value.cp = *parv;
1246 lp->flags = MODE_DEL | MODE_BAN;
1251 * limit 'l' to only *1* change per mode command but
1256 if (whatt == MODE_ADD && --parc > 0)
1260 if (whatt == MODE_DEL)
1270 if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1272 if (!(nusers = atoi(*++parv)))
1274 lp = &chops[opcnt++];
1275 lp->flags = MODE_ADD | MODE_LIMIT;
1279 sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS),
1280 me.name, cptr->name, "MODE +l");
1282 case 'i': /* falls through for default case */
1283 if (whatt == MODE_DEL)
1284 while ((lp = chptr->invites))
1285 del_invite(lp->value.cptr, chptr);
1287 for (ip = flags; *ip; ip += 2)
1288 if (*(ip + 1) == *curr)
1293 if (whatt == MODE_ADD)
1295 if (*ip == MODE_PRIVATE)
1296 newmode &= ~MODE_SECRET;
1297 else if (*ip == MODE_SECRET)
1298 newmode &= ~MODE_PRIVATE;
1304 else if (!IsServer(cptr))
1305 sendto_one(cptr, err_str(ERR_UNKNOWNMODE),
1306 me.name, cptr->name, *curr);
1311 * Make sure mode strings such as "+m +t +p +i" are parsed
1314 if (!*curr && parc > 0)
1318 /* If this was from a server, and it is the last
1319 * parameter and it starts with a digit, it must
1320 * be the creationtime. --Run
1324 if (parc == 1 && isDigit(*curr))
1326 newtime = atoi(curr);
1327 if (newtime && chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
1329 chptr->creationtime = newtime;
1338 else if (newtime > chptr->creationtime)
1339 { /* It is a net-break ride if we have ops.
1340 bounce modes if we have ops. --Run */
1343 else if (chptr->creationtime == 0)
1345 if (chptr->creationtime == 0 || doesop)
1346 chptr->creationtime = newtime;
1354 * A legal *badop can occur when two
1355 * people join simultaneously a channel,
1356 * Allow for 10 min of lag (and thus hacking
1357 * on channels younger then 10 min) --Run
1359 else if (*badop == 0 ||
1360 chptr->creationtime > (TStime() - TS_LAG_TIME))
1362 if (newtime < chptr->creationtime)
1363 chptr->creationtime = newtime;
1372 } /* end of while loop for MODE processing */
1375 * Now reject non chan ops. Accept modes from opers on local channels
1376 * even if they are deopped
1378 #ifdef OPER_MODE_LCHAN
1379 if (!IsServer(cptr) &&
1380 (!tmp || !((tmp->flags & CHFL_CHANOP) ||
1381 IsOperOnLocalChannel(sptr, chptr->chname))))
1383 if (!IsServer(cptr) && (!tmp || !(tmp->flags & CHFL_CHANOP)))
1387 return (opcnt || newmode != mode->mode || limitset || keychange) ? 0 : -1;
1390 if (doesop && newtime == 0 && IsServer(sptr))
1394 (aconf = find_conf_host(cptr->confs, sptr->name, CONF_UWORLD)))
1397 #ifdef OPER_MODE_LCHAN
1398 bounce = (*badop == 1 || *badop == 2 ||
1399 (is_deopped(sptr, chptr) &&
1400 !IsOperOnLocalChannel(sptr, chptr->chname))) ? 1 : 0;
1402 bounce = (*badop == 1 || *badop == 2 || is_deopped(sptr, chptr)) ? 1 : 0;
1406 for (ip = flags; *ip; ip += 2)
1407 if ((*ip & newmode) && !(*ip & oldm.mode))
1411 if (bwhatt != MODE_DEL)
1416 *bmbuf++ = *(ip + 1);
1420 if (whatt != MODE_ADD)
1426 *mbuf++ = *(ip + 1);
1430 for (ip = flags; *ip; ip += 2)
1431 if ((*ip & oldm.mode) && !(*ip & newmode))
1435 if (bwhatt != MODE_ADD)
1440 *bmbuf++ = *(ip + 1);
1444 if (whatt != MODE_DEL)
1450 *mbuf++ = *(ip + 1);
1455 if (limitset && !nusers && mode->limit)
1459 if (bwhatt != MODE_ADD)
1465 sprintf(numeric, "%-15d", mode->limit);
1466 if ((cp = strchr(numeric, ' ')))
1468 strcat(bpbuf, numeric);
1469 blen += strlen(numeric);
1471 strcat(nbpbuf, numeric);
1472 nblen += strlen(numeric);
1473 strcat(nbpbuf, " ");
1477 if (whatt != MODE_DEL)
1482 mode->mode &= ~MODE_LIMIT;
1488 * Reconstruct "+bkov" chain.
1494 unsigned int prev_whatt = 0;
1496 for (; i < opcnt; i++)
1500 * make sure we have correct mode change sign
1502 if (whatt != (lp->flags & (MODE_ADD | MODE_DEL)))
1504 if (lp->flags & MODE_ADD)
1518 nlen = strlen(npbuf);
1520 * get c as the mode char and tmp as a pointer to
1521 * the parameter for this mode change.
1523 switch (lp->flags & MODE_WPARAS)
1527 cp = lp->value.cptr->name;
1531 cp = lp->value.cptr->name;
1535 * I made this a bit more user-friendly (tm):
1537 * nick!user = nick!user@*
1538 * user@host = *!user@host
1539 * host.name = *!*@host.name --Run
1542 cp = pretty_mask(lp->value.cp);
1550 sprintf(numeric, "%-15d", nusers);
1551 if ((cp = strchr(numeric, ' ')))
1557 /* What could be added: cp+' '+' '+<TS>+'\0' */
1558 if (len + strlen(cp) + 13 > (size_t)MODEBUFLEN ||
1559 nlen + strlen(cp) + NUMNICKLEN + 12 > (size_t)MODEBUFLEN)
1562 switch (lp->flags & MODE_WPARAS)
1565 if (strlen(cp) > (size_t)KEYLEN)
1566 *(cp + KEYLEN) = '\0';
1567 if ((whatt == MODE_ADD && (*mode->key == '\0' ||
1568 strCasediff(mode->key, cp) != 0)) ||
1569 (whatt == MODE_DEL && (*mode->key != '\0')))
1573 if (*mode->key == '\0')
1575 if (bwhatt != MODE_DEL)
1585 nblen += strlen(cp);
1586 strcat(nbpbuf, " ");
1591 if (bwhatt != MODE_ADD)
1596 strcat(bpbuf, mode->key);
1597 blen += strlen(mode->key);
1600 strcat(nbpbuf, mode->key);
1601 nblen += strlen(mode->key);
1602 strcat(nbpbuf, " ");
1607 if (*mbuf != '+' && *mbuf != '-')
1623 if (whatt == MODE_ADD)
1624 strncpy(mode->key, cp, KEYLEN);
1631 if (nusers && nusers != mode->limit)
1635 if (mode->limit == 0)
1637 if (bwhatt != MODE_DEL)
1645 if (bwhatt != MODE_ADD)
1650 sprintf(numeric, "%-15d", mode->limit);
1651 if ((cp = strchr(numeric, ' ')))
1653 strcat(bpbuf, numeric);
1654 blen += strlen(numeric);
1657 strcat(nbpbuf, numeric);
1658 nblen += strlen(numeric);
1659 strcat(nbpbuf, " ");
1664 if (*mbuf != '+' && *mbuf != '-')
1680 mode->limit = nusers;
1686 tmp = find_user_link(chptr->members, lp->value.cptr);
1687 if (lp->flags & MODE_ADD)
1689 change = (~tmp->flags) & CHFL_OVERLAP & lp->flags;
1690 if (change && bounce)
1692 if (lp->flags & MODE_CHANOP)
1693 tmp->flags |= CHFL_DEOPPED;
1694 if (bwhatt != MODE_DEL)
1700 strcat(bpbuf, lp->value.cptr->name);
1701 blen += strlen(lp->value.cptr->name);
1704 sprintf_irc(nbpbuf + nblen, "%s%s ", NumNick(lp->value.cptr));
1705 nblen += strlen(nbpbuf + nblen);
1710 tmp->flags |= lp->flags & CHFL_OVERLAP;
1711 if (lp->flags & MODE_CHANOP)
1713 tmp->flags &= ~CHFL_DEOPPED;
1715 tmp->flags &= ~CHFL_SERVOPOK;
1721 change = tmp->flags & CHFL_OVERLAP & lp->flags;
1722 if (change && bounce)
1724 if (lp->flags & MODE_CHANOP)
1725 tmp->flags &= ~CHFL_DEOPPED;
1726 if (bwhatt != MODE_ADD)
1732 strcat(bpbuf, lp->value.cptr->name);
1733 blen += strlen(lp->value.cptr->name);
1736 sprintf_irc(nbpbuf + nblen, "%s%s ", NumNick(lp->value.cptr));
1737 blen += strlen(bpbuf + blen);
1742 tmp->flags &= ~change;
1743 if ((change & MODE_CHANOP) && IsServer(sptr))
1744 tmp->flags |= CHFL_DEOPPED;
1747 if (change || *badop == 2 || *badop == 4)
1754 sprintf_irc(npbuf + nlen, "%s%s ", NumNick(lp->value.cptr));
1755 nlen += strlen(npbuf + nlen);
1756 npbuf[nlen++] = ' ';
1762 if (*mbuf != '+' && *mbuf != '-')
1770 * Only bans aren't bounced, it makes no sense to bounce last second
1771 * bans while propagating bans done before the net.rejoin. The reason
1772 * why I don't bounce net.rejoin bans is because it is too much
1773 * work to take care of too long strings adding the necessary TS to
1774 * net.burst bans -- RunLazy
1775 * We do have to check for *badop==2 now, we don't want HACKs to take
1778 * Since BURST - I *did* implement net.rejoin ban bouncing. So now it
1779 * certainly makes sense to also bounce 'last second' bans (bans done
1780 * after the net.junction). -- RunHardWorker
1782 if ((change = (whatt & MODE_ADD) &&
1783 !add_banid(sptr, chptr, cp, !bounce, !add_banid_called)))
1784 add_banid_called = 1;
1786 change = (whatt & MODE_DEL) && !del_banid(chptr, cp, !bounce);
1788 if (bounce && change)
1791 if ((whatt & MODE_ADD))
1793 if (bwhatt != MODE_DEL)
1799 else if ((whatt & MODE_DEL))
1801 if (bwhatt != MODE_ADD)
1813 nblen += strlen(cp);
1814 strcat(nbpbuf, " ");
1832 if (*mbuf != '+' && *mbuf != '-')
1839 } /* for (; i < opcnt; i++) */
1846 if (!hacknotice && *bmodebuf && chptr->creationtime)
1848 if (Protocol(cptr) < 10)
1849 sendto_one(cptr, ":%s MODE %s %s %s " TIME_T_FMT,
1850 me.name, chptr->chname, bmodebuf, bparambuf,
1851 *badop == 2 ? (time_t) 0 : chptr->creationtime);
1853 sendto_one(cptr, "%s MODE %s %s %s " TIME_T_FMT,
1854 NumServ(&me), chptr->chname, bmodebuf, nbparambuf,
1855 *badop == 2 ? (time_t) 0 : chptr->creationtime);
1857 /* If there are possibly bans to re-add, bounce them now */
1858 if (add_banid_called && bounce)
1860 Link *ban[6]; /* Max 6 bans at a time */
1861 size_t len[6], sblen, total_len;
1862 int cnt, delayed = 0;
1863 while (delayed || (ban[0] = next_overlapped_ban()))
1865 len[0] = strlen(ban[0]->value.ban.banstr);
1866 cnt = 1; /* We already got one ban :) */
1867 sblen = sprintf_irc(sendbuf, ":%s MODE %s +b",
1868 me.name, chptr->chname) - sendbuf;
1869 total_len = sblen + 1 + len[0]; /* 1 = ' ' */
1870 /* Find more bans: */
1872 while (cnt < 6 && (ban[cnt] = next_overlapped_ban()))
1874 len[cnt] = strlen(ban[cnt]->value.ban.banstr);
1875 if (total_len + 5 + len[cnt] > BUFSIZE) /* 5 = "b \r\n\0" */
1877 delayed = cnt + 1; /* != 0 */
1880 sendbuf[sblen++] = 'b';
1881 total_len += 2 + len[cnt++]; /* 2 = "b " */
1885 sendbuf[sblen++] = ' ';
1886 strcpy(sendbuf + sblen, ban[cnt]->value.ban.banstr);
1889 sendbufto_one(cptr); /* Send bounce to uplink */
1891 ban[0] = ban[delayed - 1];
1894 /* Send -b's of overlapped bans to clients to keep them synchronized */
1895 if (add_banid_called && !bounce)
1898 char *banstr[6]; /* Max 6 bans at a time */
1899 size_t len[6], sblen, psblen, total_len;
1900 int cnt, delayed = 0;
1904 psblen = sprintf_irc(sendbuf, ":%s MODE %s -b",
1905 sptr->name, chptr->chname) - sendbuf;
1906 else /* We rely on IsRegistered(sptr) being true for MODE */
1907 psblen = sprintf_irc(sendbuf, ":%s!%s@%s MODE %s -b", sptr->name,
1908 sptr->user->username, sptr->user->host, chptr->chname) - sendbuf;
1909 while (delayed || (ban = next_removed_overlapped_ban()))
1913 len[0] = strlen((banstr[0] = ban->value.ban.banstr));
1914 ban->value.ban.banstr = NULL;
1916 cnt = 1; /* We already got one ban :) */
1918 total_len = sblen + 1 + len[0]; /* 1 = ' ' */
1919 /* Find more bans: */
1921 while (cnt < 6 && (ban = next_removed_overlapped_ban()))
1923 len[cnt] = strlen((banstr[cnt] = ban->value.ban.banstr));
1924 ban->value.ban.banstr = NULL;
1925 if (total_len + 5 + len[cnt] > BUFSIZE) /* 5 = "b \r\n\0" */
1927 delayed = cnt + 1; /* != 0 */
1930 sendbuf[sblen++] = 'b';
1931 total_len += 2 + len[cnt++]; /* 2 = "b " */
1935 sendbuf[sblen++] = ' ';
1936 strcpy(sendbuf + sblen, banstr[cnt]);
1937 RunFree(banstr[cnt]);
1940 for (lp = chptr->members; lp; lp = lp->next)
1941 if (MyConnect(acptr = lp->value.cptr) && !(lp->flags & CHFL_ZOMBIE))
1942 sendbufto_one(acptr);
1945 banstr[0] = banstr[delayed - 1];
1946 len[0] = len[delayed - 1];
1951 return gotts ? 1 : -1;
1954 /* We are now treating the <key> part of /join <channel list> <key> as a key
1955 * ring; that is, we try one key against the actual channel key, and if that
1956 * doesn't work, we try the next one, and so on. -Kev -Texaco
1957 * Returns: 0 on match, 1 otherwise
1958 * This version contributed by SeKs <intru@info.polymtl.ca>
1960 static int compall(char *key, char *keyring)
1965 p1 = key; /* point to the key... */
1966 while (*p1 && *p1 == *keyring)
1967 { /* step through the key and ring until they
1973 if (!*p1 && (!*keyring || *keyring == ','))
1974 /* ok, if we're at the end of the and also at the end of one of the keys
1975 in the keyring, we have a match */
1978 if (!*keyring) /* if we're at the end of the key ring, there
1979 weren't any matches, so we return 1 */
1982 /* Not at the end of the key ring, so step
1983 through to the next key in the ring: */
1984 while (*keyring && *(keyring++) != ',');
1986 goto top; /* and check it against the key */
1989 static int can_join(aClient *sptr, aChannel *chptr, char *key)
1992 int overrideJoin = 0;
1994 #ifdef OPER_WALK_THROUGH_LMODES
1995 /* An oper can force a join on a local channel using "OVERRIDE" as the key.
1996 a HACK(4) notice will be sent if he would not have been supposed
1997 to join normally. */
1998 if (IsOperOnLocalChannel(sptr,chptr->chname) && !BadPtr(key) &&
1999 compall("OVERRIDE",key) == 0)
2000 overrideJoin = MAGIC_OPER_OVERRIDE;
2003 * Now a banned user CAN join if invited -- Nemesi
2004 * Now a user CAN escape channel limit if invited -- bfriendly
2006 if ((chptr->mode.mode & MODE_INVITEONLY) || (is_banned(sptr, chptr, NULL)
2007 || (chptr->mode.limit && chptr->users >= chptr->mode.limit)))
2009 for (lp = sptr->user->invited; lp; lp = lp->next)
2010 if (lp->value.chptr == chptr)
2014 if (chptr->mode.limit && chptr->users >= chptr->mode.limit)
2015 return (overrideJoin + ERR_CHANNELISFULL);
2017 * This can return an "Invite only" msg instead of the "You are banned"
2018 * if _both_ conditions are true, but who can say what is more
2019 * appropriate ? checking again IsBanned would be _SO_ cpu-xpensive !
2021 return overrideJoin + ((chptr->mode.mode & MODE_INVITEONLY) ?
2022 ERR_INVITEONLYCHAN : ERR_BANNEDFROMCHAN);
2026 /* now using compall (above) to test against a whole key ring -Kev */
2027 if (*chptr->mode.key && (BadPtr(key) || compall(chptr->mode.key, key)))
2028 return overrideJoin + (ERR_BADCHANNELKEY);
2034 * Remove bells and commas from channel name
2037 static void clean_channelname(char *cn)
2052 /* Missed the Icelandic letter ETH last time: */
2053 if ((unsigned char)(*cn) == 0xd0)
2061 * Get Channel block for i (and allocate a new channel
2062 * block, if it didn't exists before).
2064 static aChannel *get_channel(aClient *cptr, char *chname, int flag)
2066 Reg1 aChannel *chptr;
2072 len = strlen(chname);
2073 if (MyUser(cptr) && len > CHANNELLEN)
2076 *(chname + CHANNELLEN) = '\0';
2078 if ((chptr = FindChannel(chname)))
2082 chptr = (aChannel *)RunMalloc(sizeof(aChannel) + len);
2084 memset(chptr, 0, sizeof(aChannel));
2085 strcpy(chptr->chname, chname);
2087 channel->prevch = chptr;
2088 chptr->prevch = NULL;
2089 chptr->nextch = channel;
2090 chptr->creationtime = MyUser(cptr) ? TStime() : (time_t) 0;
2097 static void add_invite(aClient *cptr, aChannel *chptr)
2099 Reg1 Link *inv, **tmp;
2101 del_invite(cptr, chptr);
2103 * Delete last link in chain if the list is max length
2105 if (list_length(cptr->user->invited) >= MAXCHANNELSPERUSER)
2106 del_invite(cptr, cptr->user->invited->value.chptr);
2108 * Add client to channel invite list
2111 inv->value.cptr = cptr;
2112 inv->next = chptr->invites;
2113 chptr->invites = inv;
2115 * Add channel to the end of the client invite list
2117 for (tmp = &(cptr->user->invited); *tmp; tmp = &((*tmp)->next));
2119 inv->value.chptr = chptr;
2125 * Delete Invite block from channel invite list and client invite list
2127 void del_invite(aClient *cptr, aChannel *chptr)
2129 Reg1 Link **inv, *tmp;
2131 for (inv = &(chptr->invites); (tmp = *inv); inv = &tmp->next)
2132 if (tmp->value.cptr == cptr)
2139 for (inv = &(cptr->user->invited); (tmp = *inv); inv = &tmp->next)
2140 if (tmp->value.chptr == chptr)
2148 /* List and skip all channels that are listen */
2149 void list_next_channels(aClient *cptr, int nr)
2151 aListingArgs *args = cptr->listing;
2152 aChannel *chptr = args->chptr;
2153 chptr->mode.mode &= ~MODE_LISTED;
2154 while (is_listed(chptr) || --nr >= 0)
2156 for (; chptr; chptr = chptr->nextch)
2158 if (!cptr->user || (SecretChannel(chptr) && !IsMember(cptr, chptr)))
2160 if (chptr->users > args->min_users && chptr->users < args->max_users &&
2161 chptr->creationtime > args->min_time &&
2162 chptr->creationtime < args->max_time &&
2163 (!args->topic_limits || (*chptr->topic &&
2164 chptr->topic_time > args->min_topic_time &&
2165 chptr->topic_time < args->max_topic_time)))
2167 sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name,
2168 ShowChannel(cptr, chptr) ? chptr->chname : "*",
2169 chptr->users, ShowChannel(cptr, chptr) ? chptr->topic : "");
2170 chptr = chptr->nextch;
2176 RunFree(cptr->listing);
2177 cptr->listing = NULL;
2178 sendto_one(cptr, rpl_str(RPL_LISTEND), me.name, cptr->name);
2184 cptr->listing->chptr = chptr;
2185 chptr->mode.mode |= MODE_LISTED;
2190 * Subtract one user from channel i (and free channel
2191 * block, if channel became empty).
2193 static void sub1_from_channel(aChannel *chptr)
2198 if (chptr->users > 1) /* Can be 0, called for an empty channel too */
2204 /* Channel became (or was) empty: Remove channel */
2205 if (is_listed(chptr))
2208 for (i = 0; i <= highest_fd; i++)
2211 if ((acptr = loc_clients[i]) && acptr->listing &&
2212 acptr->listing->chptr == chptr)
2214 list_next_channels(acptr, 1);
2215 break; /* Only one client can list a channel */
2220 * Now, find all invite links from channel structure
2222 while ((tmp = chptr->invites))
2223 del_invite(tmp->value.cptr, chptr);
2225 tmp = chptr->banlist;
2230 RunFree(obtmp->value.ban.banstr);
2231 RunFree(obtmp->value.ban.who);
2235 chptr->prevch->nextch = chptr->nextch;
2237 channel = chptr->nextch;
2239 chptr->nextch->prevch = chptr->prevch;
2242 RunFree((char *)chptr);
2248 * parv[0] = sender prefix
2250 * parv[2] = channel keys (client), or channel TS (server)
2252 int m_join(aClient *cptr, aClient *sptr, int parc, char *parv[])
2254 static char jbuf[BUFSIZE], mbuf[BUFSIZE];
2256 Reg3 aChannel *chptr;
2257 Reg4 char *name, *keysOrTS = NULL;
2258 int i = 0, zombie = 0, sendcreate = 0;
2259 unsigned int flags = 0;
2260 size_t jlen = 0, mlen = 0;
2262 char *p = NULL, *bufptr;
2264 if (parc < 2 || *parv[1] == '\0')
2266 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "JOIN");
2270 for (p = parv[1]; *p; p++) /* find the last "JOIN 0" in the line -Kev */
2272 && (*(p + 1) == ',' || *(p + 1) == '\0' || !isIrcCh(*(p + 1))))
2274 /* If it's a single "0", remember the place; we will start parsing
2275 the channels after the last 0 in the line -Kev */
2282 { /* Step through to the next comma or until the
2283 end of the line, in an attempt to save CPU
2285 while (*p != ',' && *p != '\0')
2291 keysOrTS = parv[2]; /* Remember where our keys are or the TS is;
2292 parv[2] needs to be NULL for the call to
2293 m_names below -Kev */
2296 *jbuf = *mbuf = '\0'; /* clear both join and mode buffers -Kev */
2298 * Rebuild list of channels joined to be the actual result of the
2299 * JOIN. Note that "JOIN 0" is the destructive problem.
2301 for (name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ","))
2304 if (MyConnect(sptr))
2305 clean_channelname(name);
2306 else if (IsLocalChannel(name))
2308 if (*name == '0' && *(name + 1) == '\0')
2310 /* Remove the user from all his channels -Kev */
2311 while ((lp = sptr->user->channel))
2313 chptr = lp->value.chptr;
2314 if (!is_zombie(sptr, chptr))
2315 sendto_channel_butserv(chptr, sptr, PartFmt2,
2316 parv[0], chptr->chname, "Left all channels");
2317 remove_user_from_channel(sptr, chptr);
2320 *mbuf = *jbuf = '\0';
2324 { /* not a /join 0, so treat it as
2325 a /join #channel -Kev */
2326 if (!IsChannelName(name))
2329 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
2333 if (MyConnect(sptr))
2336 if(bad_channel(name) && !IsAnOper(sptr))
2338 sendto_one(sptr, err_str(ERR_BADCHANNAME), me.name, parv[0],name);
2344 * Local client is first to enter previously nonexistant
2345 * channel so make them (rightfully) the Channel Operator.
2346 * This looks kind of ugly because we try to avoid calling the strlen()
2348 if (ChannelExists(name))
2350 flags = CHFL_DEOPPED;
2353 else if (strlen(name) > CHANNELLEN)
2355 *(name + CHANNELLEN) = '\0';
2356 if (ChannelExists(name))
2358 flags = CHFL_DEOPPED;
2363 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
2369 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
2373 #ifdef OPER_NO_CHAN_LIMIT
2375 * Opers are allowed to join any number of channels
2377 if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsAnOper(sptr))
2379 if (sptr->user->joined >= MAXCHANNELSPERUSER)
2382 chptr = get_channel(sptr, name, !CREATE);
2383 sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
2384 me.name, parv[0], chptr ? chptr->chname : name);
2385 break; /* Can't return, else he won't get on ANY
2386 channels! Break out of the for loop instead.
2390 chptr = get_channel(sptr, name, CREATE);
2391 if (chptr && (lp = find_user_link(chptr->members, sptr)))
2393 if (lp->flags & CHFL_ZOMBIE)
2396 flags = lp->flags & (CHFL_DEOPPED | CHFL_SERVOPOK);
2397 remove_user_from_channel(sptr, chptr);
2398 chptr = get_channel(sptr, name, CREATE);
2403 name = chptr->chname;
2404 if (!chptr->creationtime) /* A remote JOIN created this channel ? */
2405 chptr->creationtime = MAGIC_REMOTE_JOIN_TS;
2408 if (chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
2409 chptr->creationtime = atoi(keysOrTS);
2411 parc = 2; /* Don't pass it on */
2415 if (!MyConnect(sptr))
2416 flags = CHFL_DEOPPED;
2417 if (sptr->flags & FLAGS_TS8)
2418 flags |= CHFL_SERVOPOK;
2420 if (MyConnect(sptr))
2422 int created = chptr->users == 0;
2423 if (check_target_limit(sptr, chptr, chptr->chname, created))
2425 if (created) /* Did we create the channel? */
2426 sub1_from_channel(chptr); /* Remove it again! */
2429 if ((i = can_join(sptr, chptr, keysOrTS)))
2431 #ifdef OPER_WALK_THROUGH_LMODES
2432 if (i > MAGIC_OPER_OVERRIDE)
2434 switch(i - MAGIC_OPER_OVERRIDE)
2436 case ERR_CHANNELISFULL: i = 'l'; break;
2437 case ERR_INVITEONLYCHAN: i = 'i'; break;
2438 case ERR_BANNEDFROMCHAN: i = 'b'; break;
2439 case ERR_BADCHANNELKEY: i = 'k'; break;
2441 sendto_op_mask(SNO_HACK4,"OPER JOIN: %s JOIN %s (overriding +%c)",sptr->name,chptr->chname,i);
2445 sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
2449 sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
2455 * Complete user entry to the new channel (if any)
2457 add_user_to_channel(chptr, sptr, flags);
2460 * Notify all other users on the new channel
2462 sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
2466 del_invite(sptr, chptr);
2467 if (chptr->topic[0] != '\0')
2469 sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
2470 parv[0], name, chptr->topic);
2471 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0], name,
2472 chptr->topic_nick, chptr->topic_time);
2475 m_names(cptr, sptr, 2, parv);
2479 /* Select proper buffer; mbuf for creation, jbuf otherwise */
2482 continue; /* Head off local channels at the pass */
2484 bufptr = (sendcreate == 0) ? jbuf : mbuf;
2485 buflen = (sendcreate == 0) ? &jlen : &mlen;
2487 if (*buflen < BUFSIZE - len - 2)
2491 strcat(bufptr, ","); /* Add to join buf */
2494 strncat(bufptr, name, BUFSIZE - *buflen - 1);
2497 sendcreate = 0; /* Reset sendcreate */
2500 #ifndef NO_PROTOCOL9
2501 if (*jbuf || *mbuf) /* Propagate joins to P09 servers */
2502 sendto_lowprot_butone(cptr, 9, (*jbuf && *mbuf) ? ":%s JOIN %s,%s" :
2503 ":%s JOIN %s%s", parv[0], jbuf, mbuf);
2506 if (*jbuf) /* Propgate joins to P10 servers */
2508 sendto_serv_butone(cptr,
2509 parc > 2 ? ":%s JOIN %s %s" : ":%s JOIN %s", parv[0], jbuf, keysOrTS);
2511 sendto_highprot_butone(cptr, 10,
2512 parc > 2 ? ":%s JOIN %s %s" : ":%s JOIN %s", parv[0], jbuf, keysOrTS);
2514 if (*mbuf) /* and now creation events */
2516 sendto_serv_butone(cptr, "%s%s CREATE %s " TIME_T_FMT,
2517 NumNick(sptr), mbuf, TStime());
2519 sendto_highprot_butone(cptr, 10, "%s%s CREATE %s " TIME_T_FMT,
2520 NumNick(sptr), mbuf, TStime());
2524 { /* shouldn't ever set TS for remote JOIN's */
2526 { /* check for channels that need TS's */
2528 for (name = strtoken(&p, jbuf, ","); name; name = strtoken(&p, NULL, ","))
2530 chptr = get_channel(sptr, name, !CREATE);
2531 if (chptr && chptr->mode.mode & MODE_SENDTS)
2533 sendto_serv_butone(cptr, ":%s MODE %s + " TIME_T_FMT, me.name,
2534 chptr->chname, chptr->creationtime); /* ok, send TS */
2535 chptr->mode.mode &= ~MODE_SENDTS; /* reset flag */
2541 { /* ok, send along modes for creation events to P9 */
2543 for (name = strtoken(&p, mbuf, ","); name; name = strtoken(&p, NULL, ","))
2545 chptr = get_channel(sptr, name, !CREATE);
2546 sendto_lowprot_butone(cptr, 9, ":%s MODE %s +o %s " TIME_T_FMT,
2547 me.name, chptr->chname, parv[0], chptr->creationtime);
2557 * parv[0] = sender prefix
2558 * parv[1] = channel channelname
2559 * parv[2] = channel time stamp
2561 * This function does nothing, it does passes DESTRUCT to the other servers.
2562 * In the future we will start to use this message.
2565 int m_destruct(aClient *cptr, aClient *sptr, int parc, char *parv[])
2567 time_t chanTS; /* Creation time of the channel */
2569 if (parc < 3 || *parv[2] == '\0')
2573 /* Allow DESTRUCT from user */
2579 /* sanity checks: Only accept DESTRUCT messages from servers */
2580 if (!IsServer(sptr))
2583 /* Don't pass on DESTRUCT messages for channels that exist */
2584 if (FindChannel(parv[1]))
2587 chanTS = atoi(parv[2]);
2589 /* Pass on DESTRUCT message */
2590 sendto_highprot_butone(cptr, 10, "%s DESTRUCT %s " TIME_T_FMT,
2591 NumServ(sptr), parv[1], chanTS);
2599 * parv[0] = sender prefix
2600 * parv[1] = channel names
2601 * parv[2] = channel time stamp
2603 int m_create(aClient *cptr, aClient *sptr, int parc, char *parv[])
2605 char cbuf[BUFSIZE]; /* Buffer for list with channels
2606 that `sptr' really creates */
2607 time_t chanTS; /* Creation time for all channels
2608 in the comma seperated list */
2610 Reg5 aChannel *chptr;
2613 /* sanity checks: Only accept CREATE messages from servers */
2614 if (!IsServer(cptr) || parc < 3 || *parv[2] == '\0')
2617 chanTS = atoi(parv[2]);
2619 *cbuf = '\0'; /* Start with empty buffer */
2621 /* For each channel in the comma seperated list: */
2622 for (name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ","))
2624 badop = 0; /* Default is to accept the op */
2625 if ((chptr = FindChannel(name)))
2627 name = chptr->chname;
2628 if (TStime() - chanTS > TS_LAG_TIME)
2630 /* A bounce would not be accepted anyway - if we get here something
2631 is wrong with the TS clock syncing (or we have more then
2632 TS_LAG_TIME lag, or an admin is hacking */
2634 /* This causes a HACK notice on all upstream servers: */
2635 if (Protocol(cptr) < 10)
2636 sendto_one(cptr, ":%s MODE %s -o %s 0", me.name, name, sptr->name);
2638 sendto_one(cptr, ":%s MODE %s -o %s%s 0",
2639 me.name, name, NumNick(sptr));
2640 /* This causes a WALLOPS on all downstream servers and a notice to our
2642 parv[1] = name; /* Corrupt parv[1], it is not used anymore anyway */
2643 send_hack_notice(cptr, sptr, parc, parv, badop, 2);
2645 else if (chptr->creationtime && chanTS > chptr->creationtime &&
2646 chptr->creationtime != MAGIC_REMOTE_JOIN_TS)
2648 /* We (try) to bounce the mode, because the CREATE is used on an older
2649 channel, probably a net.ride */
2651 /* Send a deop upstream: */
2652 if (Protocol(cptr) < 10)
2653 sendto_one(cptr, ":%s MODE %s -o %s " TIME_T_FMT, me.name,
2654 name, sptr->name, chptr->creationtime);
2656 sendto_one(cptr, ":%s MODE %s -o %s%s " TIME_T_FMT, me.name,
2657 name, NumNick(sptr), chptr->creationtime);
2660 else /* Channel doesn't exist: create it */
2661 chptr = get_channel(sptr, name, CREATE);
2663 /* Add and mark ops */
2664 add_user_to_channel(chptr, sptr,
2665 (badop || IsModelessChannel(name)) ? CHFL_DEOPPED : CHFL_CHANOP);
2667 /* Send user join to the local clients (if any) */
2668 sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
2670 if (badop) /* handle badop: convert CREATE into JOIN */
2671 sendto_serv_butone(cptr, ":%s JOIN %s " TIME_T_FMT,
2672 sptr->name, name, chptr->creationtime);
2675 /* Send the op to local clients:
2676 (if any; extremely unlikely, but it CAN happen) */
2677 if (!IsModelessChannel(name))
2678 sendto_channel_butserv(chptr, sptr, ":%s MODE %s +o %s",
2679 sptr->user->server->name, name, parv[0]);
2681 /* Set/correct TS and add the channel to the
2682 buffer for accepted channels: */
2683 chptr->creationtime = chanTS;
2690 if (*cbuf) /* Any channel accepted with ops ? */
2693 sendto_serv_butone(cptr, "%s%s CREATE %s " TIME_T_FMT,
2694 NumNick(sptr), cbuf, chanTS);
2696 /* send CREATEs to 2.10 servers */
2697 sendto_highprot_butone(cptr, 10, "%s%s CREATE %s " TIME_T_FMT,
2698 NumNick(sptr), cbuf, chanTS);
2700 /* And JOIN + MODE to 2.9 servers; following
2701 is not needed after all are 2.10 */
2702 sendto_lowprot_butone(cptr, 9, ":%s JOIN %s", parv[0], cbuf);
2704 for (name = strtoken(&p, cbuf, ","); name; name = strtoken(&p, NULL, ","))
2705 sendto_lowprot_butone(cptr, 9, ":%s MODE %s +o %s " TIME_T_FMT,
2706 sptr->user->server->name, name, parv[0], chanTS);
2713 static size_t prefix_len;
2715 static void add_token_to_sendbuf(char *token, size_t *sblenp, int *firstp,
2716 int *send_itp, char is_a_ban, int mode)
2718 int first = *firstp;
2721 * Heh - we do not need to test if it still fits in the buffer, because
2722 * this BURST message is reconstructed from another BURST message, and
2723 * it only can become smaller. --Run
2726 if (*firstp) /* First token in this parameter ? */
2730 *send_itp = 1; /* Buffer contains data to be sent */
2731 sendbuf[(*sblenp)++] = ' ';
2734 sendbuf[(*sblenp)++] = ':'; /* Bans are always the last "parv" */
2735 sendbuf[(*sblenp)++] = is_a_ban;
2738 else /* Of course, 'send_it' is already set here */
2739 /* Seperate banmasks with a space because
2740 they can contain commas themselfs: */
2741 sendbuf[(*sblenp)++] = is_a_ban ? ' ' : ',';
2742 strcpy(sendbuf + *sblenp, token);
2743 *sblenp += strlen(token);
2744 if (!is_a_ban) /* nick list ? Need to take care
2745 of modes for nicks: */
2747 static int last_mode = 0;
2748 mode &= CHFL_CHANOP | CHFL_VOICE;
2751 if (last_mode != mode) /* Append mode like ':ov' if changed */
2754 sendbuf[(*sblenp)++] = ':';
2755 if (mode & CHFL_CHANOP)
2756 sendbuf[(*sblenp)++] = 'o';
2757 if (mode & CHFL_VOICE)
2758 sendbuf[(*sblenp)++] = 'v';
2760 sendbuf[*sblenp] = '\0';
2764 static void cancel_mode(aClient *sptr, aChannel *chptr, char m,
2765 const char *param, int *count)
2767 static char *pb, *sbp, *sbpi;
2768 int paramdoesntfit = 0;
2769 if (*count == -1) /* initialize ? */
2772 sprintf_irc(sendbuf, ":%s MODE %s -", sptr->name, chptr->chname);
2776 /* m == 0 means flush */
2781 size_t nplen = strlen(param);
2782 if (pb - parabuf + nplen + 23 > MODEBUFLEN)
2796 else if (*count == 0)
2798 if (*count == 6 || !m || paramdoesntfit)
2800 #ifndef NO_PROTOCOL9
2805 strcpy(sbp, parabuf);
2806 #ifndef NO_PROTOCOL9
2807 sbe = sbp + strlen(parabuf);
2809 for (member = chptr->members; member; member = member->next)
2810 if (MyUser(member->value.cptr))
2811 sendbufto_one(member->value.cptr);
2812 #ifndef NO_PROTOCOL9
2813 sprintf_irc(sbe, " " TIME_T_FMT, chptr->creationtime);
2814 /* Send 'sendbuf' to all 2.9 downlinks: */
2815 for (lp = me.serv->down; lp; lp = lp->next)
2816 if (Protocol(lp->value.cptr) < 10)
2817 sendbufto_one(lp->value.cptr);
2828 pb += strlen(param);
2834 * m_burst -- by Run carlo@runaway.xs4all.nl december 1995 till march 1997
2836 * parv[0] = sender prefix
2837 * parv[1] = channel name
2838 * parv[2] = channel timestamp
2839 * The meaning of the following parv[]'s depend on their first character:
2840 * If parv[n] starts with a '+':
2841 * Net burst, additive modes
2843 * parv[n+1] = <param> (optional)
2844 * parv[n+2] = <param> (optional)
2845 * If parv[n] starts with a '%', then n will be parc-1:
2846 * parv[n] = %<ban> <ban> <ban> ...
2847 * If parv[n] starts with another character:
2848 * parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
2849 * where <mode> is the channel mode (ov) of nick and all following nicks.
2852 * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
2854 * Anti net.ride code.
2856 * When the channel already exist, and its TS is larger then
2857 * the TS in the BURST message, then we cancel all existing modes.
2858 * If its is smaller then the received BURST message is ignored.
2859 * If it's equal, then the received modes are just added.
2861 int m_burst(aClient *cptr, aClient *sptr, int parc, char *parv[])
2863 Reg1 aChannel *chptr;
2865 int netride = 0, wipeout = 0, n;
2866 int send_it = 0, add_banid_not_called = 1;
2868 size_t sblen, mblen = 0;
2869 int mblen2, pblen2, cnt;
2871 char prev_key[KEYLEN + 1];
2873 #ifndef NO_PROTOCOL9
2877 /* BURST is only for servers and has at least 4 parameters */
2878 if (!IsServer(cptr) || parc < 4)
2885 if (find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))
2888 sprintf_irc(sendbuf,
2889 ":%s NOTICE * :*** Notice -- HACK(4): %s BURST %s %s", me.name,
2890 sptr->name, parv[1], parv[2]);
2891 for (i = 3; i < parc - 1; ++i)
2892 p = sprintf_irc(p, " %s", parv[i]);
2893 sprintf_irc(p, " :%s", parv[parc - 1]);
2894 sendbufto_op_mask(SNO_HACK4);
2898 #if 1 /* FIXME: This should be removed after all HUBs upgraded to ircu2.10.05 */
2900 if (MyConnect(sptr))
2902 return exit_client_msg(cptr, cptr, &me,
2903 "HACK: BURST message outside net.burst from %s", sptr->name);
2907 /* Find the channel, or create it - note that the creation time
2908 * will be 0 if it has to be created */
2909 chptr = get_channel(sptr, parv[1], CREATE);
2910 current_mode = &chptr->mode;
2911 prev_mode = chptr->mode.mode;
2912 if (*chptr->mode.key)
2914 prev_mode |= MODE_KEY;
2915 strcpy(prev_key, chptr->mode.key);
2917 if (chptr->mode.limit)
2918 prev_mode |= MODE_LIMIT;
2920 timestamp = atoi(parv[2]);
2922 /* Copy the new TS when the received creationtime appears to be older */
2923 if (!chptr->creationtime || chptr->creationtime > timestamp)
2925 /* Set the new timestamp */
2926 chptr->creationtime = timestamp;
2927 send_it = 1; /* Make sure we pass on the different timestamp ! */
2928 /* Mark all bans as needed to be wiped out */
2929 for (lp = chptr->banlist; lp; lp = lp->next)
2930 lp->flags |= CHFL_BURST_BAN_WIPEOUT;
2932 * Only the first BURST for this channel can have creationtime > timestamp,
2933 * so at this moment ALL members are on OUR side, and thus all net.riders:
2937 for (lp = chptr->members; lp; lp = lp->next)
2938 lp->flags &= ~CHFL_BURST_JOINED; /* Set later for nicks in the BURST msg */
2939 /* If `wipeout' is set then these will be deopped later. */
2941 /* If the entering creationtime is younger, ignore the modes */
2942 if (chptr->creationtime < timestamp)
2943 netride = 1; /* Only pass on the nicks (so they JOIN) */
2945 /* Prepare buffers to pass the message */
2946 *bparambuf = *bmodebuf = *parabuf = '\0';
2951 prefix_len = sblen = sprintf_irc(sendbuf, "%s BURST %s " TIME_T_FMT,
2952 NumServ(sptr), chptr->chname, chptr->creationtime) - sendbuf;
2954 /* Run over all remaining parameters */
2955 for (n = 3; n < parc; n++)
2956 switch (*parv[n]) /* What type is it ? mode, nicks or bans ? */
2958 case '+': /* modes */
2961 while (*(++p)) /* Run over all mode characters */
2963 switch (*p) /* which mode ? */
2966 * The following cases all do the following:
2967 * - In case wipeout needed, reset 'prev_mode' to indicate this
2968 * mode should not be cancelled.
2969 * - If wipeout or (not netride and the new mode is a change),
2970 * add it to bmodebuf and bparabuf for propagation.
2972 * - Add it to modebuf and parabuf for propagation to the
2973 * clients when not netride and the new mode is a change.
2975 * - If a +s is received, cancel a +p and sent a -p to the
2976 * clients too (if +p was set).
2977 * - If a +p is received and +s is set, ignore the +p.
2982 prev_mode &= ~MODE_INVITEONLY;
2983 if (!(tmp = netride ||
2984 (current_mode->mode & MODE_INVITEONLY)) || wipeout)
2986 bmodebuf[mblen++] = 'i';
2987 current_mode->mode |= MODE_INVITEONLY;
2990 modebuf[mblen2++] = 'i';
2996 char *param = parv[++n];
2997 prev_mode &= ~MODE_KEY;
2998 if (!(tmp = netride || (*current_mode->key &&
2999 (!strcmp(current_mode->key, param) ||
3000 (!wipeout && strcmp(current_mode->key, param) < 0)))) ||
3003 bmodebuf[mblen++] = 'k';
3004 strcat(bparambuf, " ");
3005 strcat(bparambuf, param);
3006 strncpy(current_mode->key, param, KEYLEN);
3008 if (!tmp && !wipeout)
3010 modebuf[mblen2++] = 'k';
3011 parabuf[pblen2++] = ' ';
3012 strcpy(parabuf + pblen2, param);
3013 pblen2 += strlen(param);
3021 unsigned int param = atoi(parv[++n]);
3022 prev_mode &= ~MODE_LIMIT;
3023 if (!(tmp = netride || (current_mode->limit &&
3024 (current_mode->limit == param ||
3025 (!wipeout && current_mode->limit < param)))) || wipeout)
3027 bmodebuf[mblen++] = 'l';
3028 sprintf_irc(bparambuf + strlen(bparambuf), " %d", param);
3029 current_mode->limit = param;
3033 modebuf[mblen2++] = 'l';
3034 pblen2 = sprintf_irc(parabuf + pblen2, " %d", param) - parabuf;
3042 prev_mode &= ~MODE_MODERATED;
3043 if (!(tmp = netride ||
3044 (current_mode->mode & MODE_MODERATED)) || wipeout)
3046 bmodebuf[mblen++] = 'm';
3047 current_mode->mode |= MODE_MODERATED;
3050 modebuf[mblen2++] = 'm';
3056 prev_mode &= ~MODE_NOPRIVMSGS;
3057 if (!(tmp = netride ||
3058 (current_mode->mode & MODE_NOPRIVMSGS)) || wipeout)
3060 bmodebuf[mblen++] = 'n';
3061 current_mode->mode |= MODE_NOPRIVMSGS;
3064 modebuf[mblen2++] = 'n';
3072 if (!netride && !wipeout && (current_mode->mode & MODE_SECRET))
3075 prev_mode &= ~MODE_PRIVATE;
3076 if (!(tmp = netride ||
3077 (current_mode->mode & MODE_PRIVATE)) || wipeout)
3079 bmodebuf[mblen++] = 'p';
3080 current_mode->mode |= MODE_PRIVATE;
3083 modebuf[mblen2++] = 'p';
3089 prev_mode &= ~MODE_SECRET;
3090 if (!(tmp = netride ||
3091 (current_mode->mode & MODE_SECRET)) || wipeout)
3093 bmodebuf[mblen++] = 's';
3094 current_mode->mode |= MODE_SECRET;
3097 modebuf[mblen2++] = 's';
3100 if (!netride && !wipeout && (current_mode->mode & MODE_PRIVATE))
3103 for (i = mblen2 - 1; i >= 0; --i)
3104 modebuf[i + 2] = modebuf[i];
3108 current_mode->mode &= ~MODE_PRIVATE;
3116 prev_mode &= ~MODE_TOPICLIMIT;
3117 if (!(tmp = netride ||
3118 (current_mode->mode & MODE_TOPICLIMIT)) || wipeout)
3120 bmodebuf[mblen++] = 't';
3121 current_mode->mode |= MODE_TOPICLIMIT;
3124 modebuf[mblen2++] = 't';
3128 } /* <-- while over all modes */
3130 bmodebuf[mblen] = '\0';
3131 sendbuf[sblen] = '\0';
3132 if (mblen) /* Anything to send at all ? */
3135 strcpy(sendbuf + sblen, " +");
3137 strcpy(sendbuf + sblen, bmodebuf);
3139 strcpy(sendbuf + sblen, bparambuf);
3140 sblen += strlen(bparambuf);
3142 break; /* Done mode part */
3144 case '%': /* bans */
3146 char *pv, *p = NULL, *ban;
3149 break; /* Ignore bans */
3150 /* Run over all bans */
3151 for (pv = parv[n] + 1; (ban = strtoken(&p, pv, " ")); pv = NULL)
3155 * The following part should do the following:
3156 * - If the new (un)ban is not a _change_ it is ignored.
3157 * - Else, add it to sendbuf for later use.
3158 * - If sendbuf is full, send it, and prepare a new
3159 * message in sendbuf.
3161 ret = add_banid(sptr, chptr, ban, 1, add_banid_not_called);
3164 add_banid_not_called = 0;
3165 /* Mark this new ban so we can send it to the clients later */
3166 chptr->banlist->flags |= CHFL_BURST_BAN;
3169 /* A new ban was added or an existing one needs to be passed on.
3170 * Also add it to sendbuf: */
3171 add_token_to_sendbuf(ban, &sblen, &first, &send_it, '%', 0);
3173 break; /* Done bans part */
3175 default: /* nicks */
3177 char *pv, *p = NULL, *nick, *ptr;
3180 int default_mode = CHFL_DEOPPED;
3181 /* Run over all nicks */
3182 for (pv = parv[n]; (nick = strtoken(&p, pv, ",")); pv = NULL)
3185 if ((ptr = strchr(nick, ':'))) /* New default mode ? */
3187 *ptr = '\0'; /* Fix 'nick' */
3188 acptr = findNUser(nick);
3191 /* Calculate new mode change: */
3192 default_mode = CHFL_DEOPPED;
3196 default_mode |= CHFL_CHANOP;
3197 default_mode &= ~CHFL_DEOPPED;
3199 else if (*ptr == 'v')
3200 default_mode |= CHFL_VOICE;
3206 acptr = findNUser(nick);
3208 * Note that at this point we already received a 'NICK' for any
3209 * <nick> numeric that is joining (and possibly opped) here.
3210 * Therefore we consider the following situations:
3211 * - The <nick> numeric exists and is from the direction of cptr: ok
3212 * - The <nick> numeric does not exist:
3213 * Apparently this previous <nick> numeric was killed (upstream)
3214 * or it collided with an existing <nick> name.
3215 * - The <nick> numeric exists but is from another direction:
3216 * Apparently this previous <nick> numeric was killed,
3217 * and due to a reroute it signed on via another link (probably
3218 * a nick [numeric] collision).
3219 * Note that it can't be a QUIT or SQUIT, because a QUIT would
3220 * come from the same direction as the BURST (cptr) while an
3221 * upstream SQUIT removes the source (server) and we would thus
3222 * have this BURST ignored already.
3223 * This means that if we find the nick and it is from the correct
3224 * direction, it joins. If it doesn't exist or is from another
3225 * direction, we have to ignore it. If all nicks are ignored, we
3226 * remove the channel again when it is empty and don't propagate
3227 * the BURST message.
3229 if (acptr && acptr->from == cptr)
3232 * The following should do the following:
3233 * - Add it to sendbuf for later use.
3234 * - If sendbuf is full, send it, and prepare a new
3235 * message in sendbuf.
3237 add_token_to_sendbuf(nick, &sblen, &first, &send_it, 0,
3239 /* Let is take effect: (Note that in the case of a netride
3240 * 'default_mode' is always CHFL_DEOPPED here). */
3241 add_user_to_channel(chptr, acptr, default_mode);
3242 chptr->members->flags |= CHFL_BURST_JOINED;
3244 } /* <-- Next nick */
3245 if (!chptr->members) /* All nicks collided and channel is empty ? */
3247 sub1_from_channel(chptr);
3248 return 0; /* Forget about the (rest of the) message... */
3250 break; /* Done nicks part */
3252 } /* <-- Next parameter if any */
3253 if (!chptr->members) /* This message only contained bans (then the previous
3254 message only contained collided nicks, see above) */
3256 sub1_from_channel(chptr);
3257 if (!add_banid_not_called)
3258 while (next_removed_overlapped_ban());
3259 return 0; /* Forget about the (rest of the) message... */
3262 /* The last (possibly only) message is always send here */
3263 if (send_it) /* Anything (left) to send ? */
3268 /* send 'sendbuf' to all downlinks */
3269 for (lp = me.serv->down; lp; lp = lp->next)
3271 if (lp->value.cptr == cptr)
3273 if (Protocol(lp->value.cptr) > 9)
3274 sendbufto_one(lp->value.cptr);
3278 * Now we finally can screw sendbuf again...
3279 * Send all changes to the local clients:
3281 * First send all joins and op them, because 2.9 servers
3282 * would protest with a HACK if we first de-opped people.
3283 * However, we don't send the +b bans yes, because we
3284 * DO first want to -b the old bans (otherwise it's confusing).
3287 /* Send all joins: */
3288 for (member = chptr->members; member; member = member->next)
3289 if (member->flags & CHFL_BURST_JOINED)
3291 sendto_channel_butserv(chptr, member->value.cptr, ":%s JOIN :%s",
3292 member->value.cptr->name, chptr->chname);
3293 #ifndef NO_PROTOCOL9
3294 /* And to 2.9 servers: */
3295 sendto_lowprot_butone(cptr, 9, ":%s JOIN %s",
3296 member->value.cptr->name, chptr->chname);
3302 /* Send all +o and +v modes: */
3303 for (member = chptr->members; member; member = member->next)
3305 if ((member->flags & CHFL_BURST_JOINED))
3307 int mode = CHFL_CHANOP;
3310 if ((member->flags & mode))
3312 modebuf[mblen2++] = (mode == CHFL_CHANOP) ? 'o' : 'v';
3313 parabuf[pblen2++] = ' ';
3314 strcpy(parabuf + pblen2, member->value.cptr->name);
3315 pblen2 += strlen(member->value.cptr->name);
3318 modebuf[mblen2] = 0;
3319 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3320 parv[0], chptr->chname, modebuf, parabuf);
3321 #ifndef NO_PROTOCOL9
3322 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3323 parv[0], chptr->chname, modebuf, parabuf,
3324 chptr->creationtime);
3333 if (mode == CHFL_CHANOP)
3341 if (cnt > 0 || mblen2 > 1)
3343 modebuf[mblen2] = 0;
3344 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3345 parv[0], chptr->chname, modebuf, parabuf);
3346 #ifndef NO_PROTOCOL9
3347 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3348 parv[0], chptr->chname, modebuf, parabuf, chptr->creationtime);
3352 #ifndef NO_PROTOCOL9
3353 else if (send_it && !ts_sent)
3355 sendto_lowprot_butone(cptr, 9, ":%s MODE %s + " TIME_T_FMT,
3356 parv[0], chptr->chname, chptr->creationtime);
3371 /* Now cancel all previous simple modes */
3372 if ((prev_mode & MODE_SECRET))
3373 cancel_mode(sptr, chptr, 's', NULL, &count);
3374 if ((prev_mode & MODE_PRIVATE))
3375 cancel_mode(sptr, chptr, 'p', NULL, &count);
3376 if ((prev_mode & MODE_MODERATED))
3377 cancel_mode(sptr, chptr, 'm', NULL, &count);
3378 if ((prev_mode & MODE_TOPICLIMIT))
3379 cancel_mode(sptr, chptr, 't', NULL, &count);
3380 if ((prev_mode & MODE_INVITEONLY))
3381 cancel_mode(sptr, chptr, 'i', NULL, &count);
3382 if ((prev_mode & MODE_NOPRIVMSGS))
3383 cancel_mode(sptr, chptr, 'n', NULL, &count);
3384 if ((prev_mode & MODE_LIMIT))
3386 current_mode->limit = 0;
3387 cancel_mode(sptr, chptr, 'l', NULL, &count);
3389 if ((prev_mode & MODE_KEY))
3391 *current_mode->key = 0;
3392 cancel_mode(sptr, chptr, 'k', prev_key, &count);
3394 current_mode->mode &= ~prev_mode;
3396 /* And deop and devoice all net.riders on my side */
3401 for (lp = chptr->members; lp; lp = lp->next)
3403 if ((lp->flags & CHFL_BURST_JOINED))
3404 continue; /* This is not a net.rider from
3405 this side of the net.junction */
3406 if ((lp->flags & mode))
3409 if (mode == CHFL_CHANOP)
3410 lp->flags |= CHFL_DEOPPED;
3411 cancel_mode(sptr, chptr, m, lp->value.cptr->name, &count);
3414 if (mode == CHFL_VOICE)
3420 /* And finally wipeout all bans that are left */
3421 for (ban = &chptr->banlist; *ban;)
3424 if ((tmp->flags & CHFL_BURST_BAN_WIPEOUT))
3426 cancel_mode(sptr, chptr, 'b', tmp->value.ban.banstr, &count);
3427 /* Copied from del_banid(): */
3429 RunFree(tmp->value.ban.banstr);
3430 RunFree(tmp->value.ban.who);
3432 /* Erase ban-valid-bit, for channel members that are banned */
3433 for (tmp = chptr->members; tmp; tmp = tmp->next)
3434 if ((tmp->flags & (CHFL_BANNED | CHFL_BANVALID)) ==
3435 (CHFL_BANNED | CHFL_BANVALID))
3436 tmp->flags &= ~CHFL_BANVALID; /* `tmp' == channel member */
3441 /* Also wipeout overlapped bans */
3442 if (!add_banid_not_called)
3445 while ((ban = next_removed_overlapped_ban()))
3446 cancel_mode(sptr, chptr, 'b', ban->value.ban.banstr, &count);
3448 cancel_mode(sptr, chptr, 0, NULL, &count); /* flush */
3451 if (send_it && !netride)
3456 if (add_banid_not_called || !(bl = next_removed_overlapped_ban()))
3459 bl = chptr->banlist;
3475 nblen = strlen(bl->value.ban.banstr);
3476 if (cnt == 6 || (!bl && cnt) || pblen2 + nblen + 12 > MODEBUFLEN) /* The last check is to make sure
3477 that the receiving 2.9 will
3478 still process this */
3480 /* Time to send buffer */
3481 modebuf[mblen2] = 0;
3482 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3483 parv[0], chptr->chname, modebuf, parabuf);
3484 #ifndef NO_PROTOCOL9
3485 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s",
3486 parv[0], chptr->chname, modebuf, parabuf);
3488 *modebuf = deban ? '-' : '+';
3493 if (!bl) /* Done ? */
3495 if (deban || (bl->flags & CHFL_BURST_BAN))
3497 /* Add ban to buffers and remove it */
3498 modebuf[mblen2++] = 'b';
3499 parabuf[pblen2++] = ' ';
3500 strcpy(parabuf + pblen2, bl->value.ban.banstr);
3503 bl->flags &= ~CHFL_BURST_BAN;
3507 if (!(bl = next_removed_overlapped_ban()))
3510 modebuf[mblen2++] = '+';
3511 bl = chptr->banlist;
3517 /* Flush MODE [-b]+b ...: */
3518 if (cnt > 0 || mblen2 > 1)
3520 modebuf[mblen2] = 0;
3521 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3522 parv[0], chptr->chname, modebuf, parabuf);
3523 #ifndef NO_PROTOCOL9
3524 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3525 parv[0], chptr->chname, modebuf, parabuf, chptr->creationtime);
3528 #ifndef NO_PROTOCOL9
3529 else if (send_it && !ts_sent)
3530 sendto_lowprot_butone(cptr, 9, ":%s MODE %s + " TIME_T_FMT,
3531 parv[0], chptr->chname, chptr->creationtime);
3541 * parv[0] = sender prefix
3543 * parv[parc - 1] = comment
3545 int m_part(aClient *cptr, aClient *sptr, int parc, char *parv[])
3547 Reg1 aChannel *chptr;
3549 char *p = NULL, *name, pbuf[BUFSIZE];
3550 char *comment = (parc > 2 && !BadPtr(parv[parc - 1])) ? parv[parc - 1] : NULL;
3552 *pbuf = '\0'; /* Initialize the part buffer... -Kev */
3554 sptr->flags &= ~FLAGS_TS8;
3556 if (parc < 2 || parv[1][0] == '\0')
3558 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "PART");
3562 for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
3564 chptr = get_channel(sptr, name, !CREATE);
3567 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
3570 if (*name == '&' && !MyUser(sptr))
3572 /* Do not use IsMember here: zombies must be able to part too */
3573 if (!(lp = find_user_link(chptr->members, sptr)))
3575 /* Normal to get when our client did a kick
3576 for a remote client (who sends back a PART),
3577 so check for remote client or not --Run */
3579 sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
3583 /* Recreate the /part list for sending to servers */
3590 if (can_send(sptr, chptr) != 0) /* Returns 0 if we CAN send */
3592 /* Send part to all clients */
3593 if (!(lp->flags & CHFL_ZOMBIE))
3596 sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], chptr->chname,
3599 sendto_channel_butserv(chptr, sptr, PartFmt1, parv[0], chptr->chname);
3601 else if (MyUser(sptr))
3604 sendto_one(sptr, PartFmt2, parv[0], chptr->chname, comment);
3606 sendto_one(sptr, PartFmt1, parv[0], chptr->chname);
3608 remove_user_from_channel(sptr, chptr);
3610 /* Send out the parts to all servers... -Kev */
3614 sendto_serv_butone(cptr, PartFmt2, parv[0], pbuf, comment);
3616 sendto_serv_butone(cptr, PartFmt1, parv[0], pbuf);
3624 * parv[0] = sender prefix
3626 * parv[2] = client to kick
3627 * parv[parc-1] = kick comment
3629 int m_kick(aClient *cptr, aClient *sptr, int parc, char *parv[])
3636 sptr->flags &= ~FLAGS_TS8;
3638 if (parc < 3 || *parv[1] == '\0')
3640 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KICK");
3645 send_hack_notice(cptr, sptr, parc, parv, 1, 3);
3647 comment = (BadPtr(parv[parc - 1])) ? parv[0] : parv[parc - 1];
3648 if (strlen(comment) > (size_t)TOPICLEN)
3649 comment[TOPICLEN] = '\0';
3651 *nickbuf = *buf = '\0';
3653 chptr = get_channel(sptr, parv[1], !CREATE);
3656 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
3659 if (IsLocalChannel(parv[1]) && !MyUser(sptr))
3661 if (IsModelessChannel(parv[1]))
3663 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
3667 if (!IsServer(cptr) && !is_chan_op(sptr, chptr))
3669 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3670 me.name, parv[0], chptr->chname);
3674 lp2 = find_user_link(chptr->members, sptr);
3675 if (MyUser(sptr) || Protocol(cptr) < 10)
3677 if (!(who = find_chasing(sptr, parv[2], NULL)))
3678 return 0; /* No such user left! */
3680 else if (!(who = findNUser(parv[2])))
3681 return 0; /* No such user left! */
3682 /* if the user is +k, prevent a kick from local user */
3683 if (IsChannelService(who) && MyUser(sptr))
3685 sendto_one(sptr, err_str(ERR_ISCHANSERVICE), me.name,
3686 parv[0], who->name, chptr->chname);
3689 #ifdef NO_OPER_DEOP_LCHAN
3691 * Prevent kicking opers from local channels -DM-
3693 if (IsOperOnLocalChannel(who, chptr->chname))
3695 sendto_one(sptr, err_str(ERR_ISOPERLCHAN), me.name,
3696 parv[0], who->name, chptr->chname);
3701 if (((lp = find_user_link(chptr->members, who)) &&
3702 !(lp->flags & CHFL_ZOMBIE)) || IsServer(sptr))
3704 if (who->from != cptr &&
3705 ((lp2 && (lp2->flags & CHFL_DEOPPED)) || (!lp2 && IsUser(sptr))))
3709 * cptr must be a server (or cptr == sptr and
3710 * sptr->flags can't have DEOPPED set
3711 * when CHANOP is set).
3713 sendto_one(cptr, ":%s JOIN %s", who->name, parv[1]);
3714 if (lp->flags & CHFL_CHANOP)
3716 if (Protocol(cptr) < 10)
3717 sendto_one(cptr, ":%s MODE %s +o %s " TIME_T_FMT,
3718 me.name, parv[1], who->name, chptr->creationtime);
3720 sendto_one(cptr, "%s MODE %s +o %s%s " TIME_T_FMT,
3721 NumServ(&me), parv[1], NumNick(who), chptr->creationtime);
3723 if (lp->flags & CHFL_VOICE)
3725 if (Protocol(cptr) < 10)
3726 sendto_one(cptr, ":%s MODE %s +v %s " TIME_T_FMT,
3727 me.name, chptr->chname, who->name, chptr->creationtime);
3729 sendto_one(cptr, "%s MODE %s +v %s%s " TIME_T_FMT,
3730 NumServ(&me), parv[1], NumNick(who), chptr->creationtime);
3736 sendto_channel_butserv(chptr, sptr,
3737 ":%s KICK %s %s :%s", parv[0], chptr->chname, who->name, comment);
3738 if (!IsLocalChannel(parv[1]))
3740 sendto_lowprot_butone(cptr, 9, ":%s KICK %s %s :%s",
3741 parv[0], chptr->chname, who->name, comment);
3742 sendto_highprot_butone(cptr, 10, ":%s KICK %s %s%s :%s",
3743 parv[0], parv[1], NumNick(who), comment);
3754 * X --a--> A --b--> B --d--> D
3758 * Where `who' is being KICK-ed by a "KICK" message received by server 'A'
3759 * via 'a', or on server 'B' via either 'b' or 'c', or on server D via 'd'.
3761 * a) On server A : set CHFL_ZOMBIE for `who' (lp) and pass on the KICK.
3762 * Remove the user immedeately when no users are left on the channel.
3763 * b) On server B : remove the user (who/lp) from the channel, send a
3764 * PART upstream (to A) and pass on the KICK.
3765 * c) KICKed by `client'; On server B : remove the user (who/lp) from the
3766 * channel, and pass on the KICK.
3767 * d) On server D : remove the user (who/lp) from the channel, and pass on
3771 * - Setting the ZOMBIE flag never hurts, we either remove the
3772 * client after that or we don't.
3773 * - The KICK message was already passed on, as should be in all cases.
3774 * - `who' is removed in all cases except case a) when users are left.
3775 * - A PART is only sent upstream in case b).
3781 * 1 --- 2 --- 3 --- 4 --- 5
3785 * We also need to turn 'who' into a zombie on servers 1 and 6,
3786 * because a KICK from 'who' (kicking someone else in that direction)
3787 * can arrive there afterwards - which should not be bounced itself.
3788 * Therefore case a) also applies for servers 1 and 6.
3792 /* Default for case a): */
3793 lp->flags |= CHFL_ZOMBIE;
3794 /* Case b) or c) ?: */
3795 if (MyUser(who)) /* server 4 */
3797 if (IsServer(cptr)) /* Case b) ? */
3798 sendto_one(cptr, PartFmt1, who->name, parv[1]);
3799 remove_user_from_channel(who, chptr);
3802 if (who->from == cptr) /* True on servers 1, 5 and 6 */
3804 aClient *acptr = IsServer(sptr) ? sptr : sptr->user->server;
3805 for (; acptr != &me; acptr = acptr->serv->up)
3806 if (acptr == who->user->server) /* Case d) (server 5) */
3808 remove_user_from_channel(who, chptr);
3812 /* Case a) (servers 1, 2, 3 and 6) */
3813 for (lp = chptr->members; lp; lp = lp->next)
3814 if (!(lp->flags & CHFL_ZOMBIE))
3817 remove_user_from_channel(who, chptr);
3820 sendto_op_mask(SNO_HACK2, "%s is now a zombie on %s",
3821 who->name, chptr->chname);
3826 else if (MyUser(sptr))
3827 sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
3828 me.name, parv[0], who->name, chptr->chname);
3836 * parv[0] = sender prefix
3838 * parv[parc - 1] = topic (if parc > 2)
3840 int m_topic(aClient *cptr, aClient *sptr, int parc, char *parv[])
3843 char *topic = NULL, *name, *p = NULL;
3847 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "TOPIC");
3852 topic = parv[parc - 1];
3854 for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
3857 if (!IsChannelName(name) || !(chptr = FindChannel(name)) ||
3858 ((topic || SecretChannel(chptr)) && !IsMember(sptr, chptr)))
3860 sendto_one(sptr, err_str(chptr ? ERR_NOTONCHANNEL : ERR_NOSUCHCHANNEL),
3861 me.name, parv[0], chptr ? chptr->chname : name);
3864 if (IsModelessChannel(name))
3866 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
3870 if (IsLocalChannel(name) && !MyUser(sptr))
3873 if (!topic) /* only asking for topic */
3875 if (chptr->topic[0] == '\0')
3876 sendto_one(sptr, rpl_str(RPL_NOTOPIC), me.name, parv[0], chptr->chname);
3879 sendto_one(sptr, rpl_str(RPL_TOPIC),
3880 me.name, parv[0], chptr->chname, chptr->topic);
3881 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME),
3882 me.name, parv[0], chptr->chname,
3883 chptr->topic_nick, chptr->topic_time);
3886 else if (((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
3887 is_chan_op(sptr, chptr)) && topic)
3889 /* setting a topic */
3890 strncpy(chptr->topic, topic, TOPICLEN);
3891 strncpy(chptr->topic_nick, sptr->name, NICKLEN);
3892 chptr->topic_time = now;
3893 sendto_serv_butone(cptr, ":%s TOPIC %s :%s",
3894 parv[0], chptr->chname, chptr->topic);
3895 sendto_channel_butserv(chptr, sptr, ":%s TOPIC %s :%s",
3896 parv[0], chptr->chname, chptr->topic);
3899 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3900 me.name, parv[0], chptr->chname);
3907 * parv[0] - sender prefix
3908 * parv[1] - user to invite
3909 * parv[2] - channel name
3911 * - INVITE now is accepted only if who does it is chanop (this of course
3912 * implies that channel must exist and he must be on it).
3914 * - On the other side it IS processed even if channel is NOT invite only
3915 * leaving room for other enhancements like inviting banned ppl. -- Nemesi
3918 int m_invite(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
3923 if (parc < 3 || *parv[2] == '\0')
3925 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "INVITE");
3929 if (!(acptr = FindUser(parv[1])))
3931 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
3935 if (is_silenced(sptr, acptr))
3939 clean_channelname(parv[2]);
3940 else if (IsLocalChannel(parv[2]))
3943 if (*parv[2] == '0' || !IsChannelName(parv[2]))
3946 if (!(chptr = FindChannel(parv[2])))
3948 if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2]))
3950 sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], parv[2]);
3954 /* Do not disallow to invite to non-existant #channels, otherwise they
3955 would simply first be created, causing only MORE bandwidth usage. */
3956 if (MyConnect(sptr))
3958 if (check_target_limit(sptr, acptr, acptr->name, 0))
3961 sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
3962 acptr->name, parv[2]);
3964 if (acptr->user->away)
3965 sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
3966 acptr->name, acptr->user->away);
3969 sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
3970 acptr->name, parv[2]);
3975 if (!IsMember(sptr, chptr))
3977 sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
3982 if (IsMember(acptr, chptr))
3984 sendto_one(sptr, err_str(ERR_USERONCHANNEL),
3985 me.name, parv[0], acptr->name, chptr->chname);
3989 if (MyConnect(sptr))
3991 if (!is_chan_op(sptr, chptr))
3993 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3994 me.name, parv[0], chptr->chname);
3998 /* If we get here, it was a VALID and meaningful INVITE */
4000 if (check_target_limit(sptr, acptr, acptr->name, 0))
4003 sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
4004 acptr->name, chptr->chname);
4006 if (acptr->user->away)
4007 sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
4008 acptr->name, acptr->user->away);
4011 if (MyConnect(acptr))
4012 add_invite(acptr, chptr);
4014 sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
4015 acptr->name, chptr->chname);
4020 static int number_of_zombies(aChannel *chptr)
4024 for (lp = chptr->members; lp; lp = lp->next)
4025 if (lp->flags & CHFL_ZOMBIE)
4033 * parv[0] = sender prefix
4034 * parv[1] = channel list or user/time limit
4035 * parv[2...] = more user/time limits
4037 int m_list(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
4040 char *name, *p = NULL;
4041 int show_usage = 0, show_channels = 0, param;
4042 aListingArgs args = {
4043 2147483647, /* max_time */
4045 4294967295U, /* max_users */
4047 0, /* topic_limits */
4048 2147483647, /* max_topic_time */
4049 0, /* min_topic_time */
4053 if (sptr->listing) /* Already listing ? */
4055 sptr->listing->chptr->mode.mode &= ~MODE_LISTED;
4056 RunFree(sptr->listing);
4057 sptr->listing = NULL;
4058 sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, sptr->name);
4060 return 0; /* Let LIST abort a listing. */
4063 if (parc < 2) /* No arguments given to /LIST ? */
4065 #ifdef DEFAULT_LIST_PARAM
4066 static char *defparv[MAXPARA + 1];
4067 static int defparc = 0;
4068 static char lp[] = DEFAULT_LIST_PARAM;
4076 defparv[defparc++] = t = strtok(s, " ");
4077 while (t && defparc < MAXPARA)
4079 if ((t = strtok(NULL, " ")))
4080 defparv[defparc++] = t;
4083 for (i = 1; i < defparc; i++)
4084 parv[i] = defparv[i];
4087 #endif /* DEFAULT_LIST_PARAM */
4090 /* Decode command */
4091 for (param = 1; !show_usage && parv[param]; param++)
4093 char *p = parv[param];
4102 args.topic_limits = 1;
4108 if (*p != '<' && *p != '>')
4124 time_t val = atoi(p);
4127 if (val < 80000000) /* Toggle UTC/offset */
4131 * 'TStime() - chptr->creationtime < val * 60'
4133 * 'chptr->creationtime > TStime() - val * 60'
4136 args.min_time = TStime() - val * 60;
4138 args.min_topic_time = TStime() - val * 60;
4140 else if (is_time == 1) /* Creation time in UTC was entered */
4141 args.max_time = val;
4142 else /* Topic time in UTC was entered */
4143 args.max_topic_time = val;
4145 else if (val < 80000000)
4148 args.max_time = TStime() - val * 60;
4150 args.max_topic_time = TStime() - val * 60;
4152 else if (is_time == 1)
4153 args.min_time = val;
4155 args.min_topic_time = val;
4157 else if (p[-1] == '<')
4158 args.max_users = atoi(p);
4160 args.min_users = atoi(p);
4161 if ((p = strchr(p, ',')))
4167 if (!IsChannelName(p))
4172 if (parc != 2) /* Don't allow a mixture of channels with <,> */
4179 while (!show_usage && p); /* p points after comma, or is NULL */
4184 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4185 "Usage: \002/QUOTE LIST\002 \037parameters\037");
4186 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4187 "Where \037parameters\037 is a space or comma seperated "
4188 "list of one or more of:");
4189 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4190 " \002<\002\037max_users\037 ; Show all channels with less "
4191 "than \037max_users\037.");
4192 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4193 " \002>\002\037min_users\037 ; Show all channels with more "
4194 "than \037min_users\037.");
4195 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4196 " \002C<\002\037max_minutes\037 ; Channels that exist less "
4197 "than \037max_minutes\037.");
4198 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4199 " \002C>\002\037min_minutes\037 ; Channels that exist more "
4200 "than \037min_minutes\037.");
4201 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4202 " \002T<\002\037max_minutes\037 ; Channels with a topic last "
4203 "set less than \037max_minutes\037 ago.");
4204 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4205 " \002T>\002\037min_minutes\037 ; Channels with a topic last "
4206 "set more than \037min_minutes\037 ago.");
4207 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4208 "Example: LIST <3,>1,C<10,T>0 ; 2 users, younger than 10 min., "
4213 sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, parv[0]);
4217 if (args.max_users > args.min_users + 1 && args.max_time > args.min_time &&
4218 args.max_topic_time > args.min_topic_time) /* Sanity check */
4220 if ((sptr->listing = (aListingArgs *)RunMalloc(sizeof(aListingArgs))))
4222 memcpy(sptr->listing, &args, sizeof(aListingArgs));
4223 if ((sptr->listing->chptr = channel))
4225 int m = channel->mode.mode & MODE_LISTED;
4226 list_next_channels(sptr, 64);
4227 channel->mode.mode |= m;
4230 RunFree(sptr->listing);
4231 sptr->listing = NULL;
4234 sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
4238 for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
4240 chptr = FindChannel(name);
4241 if (chptr && ShowChannel(sptr, chptr) && sptr->user)
4242 sendto_one(sptr, rpl_str(RPL_LIST), me.name, parv[0],
4243 ShowChannel(sptr, chptr) ? chptr->chname : "*",
4244 chptr->users - number_of_zombies(chptr), chptr->topic);
4247 sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
4252 * m_names - Added by Jto 27 Apr 1989
4254 * parv[0] = sender prefix
4257 int m_names(aClient *cptr, aClient *sptr, int parc, char *parv[])
4259 Reg1 aChannel *chptr;
4260 Reg2 aClient *c2ptr;
4262 aChannel *ch2ptr = NULL;
4263 int idx, flag, len, mlen;
4264 char *s, *para = parc > 1 ? parv[1] : NULL;
4266 if (parc > 2 && hunt_server(1, cptr, sptr, ":%s NAMES %s %s", 2, parc, parv))
4269 mlen = strlen(me.name) + 10 + strlen(sptr->name);
4273 s = strchr(para, ',');
4277 m_names(cptr, sptr, parc, parv);
4279 clean_channelname(para);
4280 ch2ptr = FindChannel(para);
4284 * First, do all visible channels (public and the one user self is)
4287 for (chptr = channel; chptr; chptr = chptr->nextch)
4289 if ((chptr != ch2ptr) && !BadPtr(para))
4290 continue; /* -- wanted a specific channel */
4291 if (!MyConnect(sptr) && BadPtr(para))
4294 if (!ShowChannel(sptr, chptr))
4295 continue; /* -- users on this are not listed */
4298 /* Find users on same channel (defined by chptr) */
4301 len = strlen(chptr->chname);
4302 strcpy(buf + 2, chptr->chname);
4303 strcpy(buf + 2 + len, " :");
4305 if (PubChannel(chptr))
4307 else if (SecretChannel(chptr))
4311 for (lp = chptr->members; lp; lp = lp->next)
4313 c2ptr = lp->value.cptr;
4315 if (sptr != c2ptr && IsInvisible(c2ptr) && !IsMember(sptr, chptr))
4318 if (lp->flags & CHFL_ZOMBIE)
4320 if (lp->value.cptr != sptr)
4328 else if (lp->flags & CHFL_CHANOP)
4333 else if (lp->flags & CHFL_VOICE)
4338 strcat(buf, c2ptr->name);
4340 idx += strlen(c2ptr->name) + 1;
4345 sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
4346 if (c2ptr != findNUser(yxx))
4348 sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
4351 if (mlen + idx + NICKLEN + 11 > BUFSIZE)
4353 if (mlen + idx + NICKLEN + 5 > BUFSIZE)
4355 /* space, modifier, nick, \r \n \0 */
4357 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4359 strncpy(buf + 2, chptr->chname, len + 1);
4362 if (PubChannel(chptr))
4364 else if (SecretChannel(chptr))
4371 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4375 sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
4376 ch2ptr ? ch2ptr->chname : para);
4380 /* Second, do all non-public, non-secret channels in one big sweep */
4382 strcpy(buf, "* * :");
4385 for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
4388 int showflag = 0, secret = 0;
4391 if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
4396 lp = c2ptr->user->channel;
4398 * Don't show a client if they are on a secret channel or when
4399 * they are on a channel sptr is on since they have already
4400 * been show earlier. -avalon
4404 ch3ptr = lp->value.chptr;
4406 if (PubChannel(ch3ptr) || IsMember(sptr, ch3ptr))
4409 if (SecretChannel(ch3ptr))
4413 if (showflag) /* Have we already shown them ? */
4416 if (secret) /* On any secret channels ? */
4419 strcat(buf, c2ptr->name);
4421 idx += strlen(c2ptr->name) + 1;
4426 sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
4427 if (c2ptr != findNUser(yxx))
4429 sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
4434 if (mlen + idx + NICKLEN + 9 > BUFSIZE)
4436 if (mlen + idx + NICKLEN + 3 > BUFSIZE) /* space, \r\n\0 */
4439 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4440 strcpy(buf, "* * :");
4446 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4447 sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
4451 void send_user_joins(aClient *cptr, aClient *user)
4454 Reg2 aChannel *chptr;
4455 Reg3 int cnt = 0, len = 0, clen;
4459 strcpy(buf + 1, user->name);
4460 strcat(buf, " JOIN ");
4461 len = strlen(user->name) + 7;
4463 for (lp = user->user->channel; lp; lp = lp->next)
4465 chptr = lp->value.chptr;
4466 if ((mask = strchr(chptr->chname, ':')))
4467 if (match(++mask, cptr->name))
4469 if (*chptr->chname == '&')
4471 if (is_zombie(user, chptr))
4473 clen = strlen(chptr->chname);
4474 if (clen + 1 + len > BUFSIZE - 3)
4478 buf[len - 1] = '\0';
4479 sendto_one(cptr, "%s", buf);
4482 strcpy(buf + 1, user->name);
4483 strcat(buf, " JOIN ");
4484 len = strlen(user->name) + 7;
4487 strcpy(buf + len, chptr->chname);
4497 sendto_one(cptr, "%s", buf);
4503 * send_hack_notice()
4505 * parc & parv[] are the same as that of the calling function:
4506 * mtype == 1 is from m_mode, 2 is from m_create, 3 is from m_kick.
4508 * This function prepares sendbuf with the server notices and wallops
4509 * to be sent for all hacks. -Ghostwolf 18-May-97
4512 static void send_hack_notice(aClient *cptr, aClient *sptr, int parc,
4513 char *parv[], int badop, int mtype)
4516 static char params[MODEBUFLEN];
4518 chptr = FindChannel(parv[1]);
4521 if (Protocol(cptr) < 10) /* We don't get numeric nicks from P09 */
4522 { /* servers, so this can be sent "As Is" */
4527 strcat(params, " ");
4528 strcat(params, parv[i++]);
4530 sprintf_irc(sendbuf,
4531 ":%s NOTICE * :*** Notice -- %sHACK(%d): %s MODE %s %s%s [" TIME_T_FMT
4532 "]", me.name, (badop == 3) ? "BOUNCE or " : "", badop, parv[0],
4533 parv[1], parv[2], params, chptr->creationtime);
4534 sendbufto_op_mask((badop == 3) ? SNO_HACK3 : (badop ==
4535 4) ? SNO_HACK4 : SNO_HACK2);
4537 if ((IsServer(sptr)) && (badop == 2))
4539 sprintf_irc(sendbuf, ":%s DESYNCH :HACK: %s MODE %s %s%s",
4540 me.name, parv[0], parv[1], parv[2], params);
4541 sendbufto_serv_butone(cptr);
4544 else if (mtype == 3)
4546 sprintf_irc(sendbuf,
4547 ":%s NOTICE * :*** Notice -- HACK: %s KICK %s %s :%s",
4548 me.name, sptr->name, parv[1], parv[2], parv[3]);
4549 sendbufto_op_mask(SNO_HACK4);
4554 /* P10 servers require numeric nick conversion before sending. */
4557 case 1: /* Convert nicks for MODE HACKs here */
4559 char *mode = parv[2];
4562 while (*mode && *mode != 'o' && *mode != 'v')
4564 strcat(params, " ");
4565 if (*mode == 'o' || *mode == 'v')
4567 register aClient *acptr;
4568 if ((acptr = findNUser(parv[i])) != NULL) /* Convert nicks here */
4569 strcat(params, acptr->name);
4572 strcat(params, "<");
4573 strcat(params, parv[i]);
4574 strcat(params, ">");
4577 else /* If it isn't a numnick, send it 'as is' */
4578 strcat(params, parv[i]);
4581 sprintf_irc(sendbuf,
4582 ":%s NOTICE * :*** Notice -- %sHACK(%d): %s MODE %s %s%s ["
4583 TIME_T_FMT "]", me.name, (badop == 3) ? "BOUNCE or " : "", badop,
4584 parv[0], parv[1], parv[2], params, chptr->creationtime);
4585 sendbufto_op_mask((badop == 3) ? SNO_HACK3 : (badop ==
4586 4) ? SNO_HACK4 : SNO_HACK2);
4588 if ((IsServer(sptr)) && (badop == 2))
4590 sprintf_irc(sendbuf, ":%s DESYNCH :HACK: %s MODE %s %s%s",
4591 me.name, parv[0], parv[1], parv[2], params);
4592 sendbufto_serv_butone(cptr);
4596 case 2: /* No conversion is needed for CREATE; the only numnick is sptr */
4598 sendto_serv_butone(cptr, ":%s DESYNCH :HACK: %s CREATE %s %s",
4599 me.name, sptr->name, chptr->chname, parv[2]);
4600 sendto_op_mask(SNO_HACK2, "HACK(2): %s CREATE %s %s",
4601 sptr->name, chptr->chname, parv[2]);
4604 case 3: /* Convert nick in KICK message */
4607 if ((acptr = findNUser(parv[2])) != NULL) /* attempt to convert nick */
4608 sprintf_irc(sendbuf,
4609 ":%s NOTICE * :*** Notice -- HACK: %s KICK %s %s :%s",
4610 me.name, sptr->name, parv[1], acptr->name, parv[3]);
4611 else /* if conversion fails, send it 'as is' in <>'s */
4612 sprintf_irc(sendbuf,
4613 ":%s NOTICE * :*** Notice -- HACK: %s KICK %s <%s> :%s",
4614 me.name, sptr->name, parv[1], parv[2], parv[3]);
4615 sendbufto_op_mask(SNO_HACK4);