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 sendbuf[sblen++] = ':';
732 if (lp1->flags & CHFL_CHANOP)
733 sendbuf[sblen++] = 'o';
734 if (lp1->flags & CHFL_VOICE)
735 sendbuf[sblen++] = 'v';
744 /* Attach all bans, space seperated " :%ban ban ..." */
745 for (first = 2; lp2; lp2 = lp2->next)
747 len = strlen(lp2->value.ban.banstr);
748 if (sblen + len + 1 + first > BUFSIZE - 3)
749 /* The +1 stands for the added ' '.
750 * The +first stands for the added ":%".
751 * The -3 is for the "\r\n\0" that is added in send.c
760 sendbuf[sblen++] = ' ';
761 sendbuf[sblen++] = ':'; /* Will be last parameter */
762 sendbuf[sblen++] = '%'; /* To tell bans apart */
765 sendbuf[sblen++] = ' ';
766 strcpy(sendbuf + sblen, lp2->value.ban.banstr);
771 sendbuf[sblen] = '\0';
772 sendbufto_one(cptr); /* Send this message */
773 } /* Continue when there was something
774 that didn't fit (full==1) */
784 int m_mode(aClient *cptr, aClient *sptr, int parc, char *parv[])
789 /* Now, try to find the channel in question */
792 chptr = FindChannel(parv[1]);
793 if (chptr == NullChn)
794 return m_umode(cptr, sptr, parc, parv);
798 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "MODE");
802 sptr->flags &= ~FLAGS_TS8;
805 clean_channelname(parv[1]);
806 else if (IsLocalChannel(parv[1]))
809 /* sending an error wasnt good, lets just send an empty mode reply.. poptix */
810 if (IsModelessChannel(chptr->chname))
813 sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],
814 chptr->chname, "+nt", "");
820 *modebuf = *parabuf = '\0';
822 channel_modes(sptr, modebuf, parabuf, chptr);
823 sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],
824 chptr->chname, modebuf, parabuf);
825 sendto_one(sptr, rpl_str(RPL_CREATIONTIME), me.name, parv[0],
826 chptr->chname, chptr->creationtime);
830 LocalChanOperMode = 0;
832 if (!(sendts = set_mode(cptr, sptr, chptr, parc - 2, parv + 2,
833 modebuf, parabuf, nparabuf, &badop)))
835 sendto_one(sptr, err_str(IsMember(sptr, chptr) ? ERR_CHANOPRIVSNEEDED :
836 ERR_NOTONCHANNEL), me.name, parv[0], chptr->chname);
841 send_hack_notice(cptr, sptr, parc, parv, badop, 1);
843 if (strlen(modebuf) > (size_t)1 || sendts > 0)
845 if (badop != 2 && strlen(modebuf) > (size_t)1)
847 #ifdef OPER_MODE_LCHAN
848 if (LocalChanOperMode) {
849 sendto_channel_butserv(chptr, &me, ":%s MODE %s %s %s",
850 me.name, chptr->chname, modebuf, parabuf);
851 sendto_op_mask(SNO_HACK4,
852 "OPER MODE: %s MODE %s %s %s",
853 sptr->name,chptr->chname,modebuf,parabuf);
857 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s",
858 parv[0], chptr->chname, modebuf, parabuf);
860 if (IsLocalChannel(chptr->chname))
862 /* We send a creationtime of 0, to mark it as a hack --Run */
863 if (IsServer(sptr) && (badop == 2 || sendts > 0))
865 if (*modebuf == '\0')
866 strcpy(modebuf, "+");
869 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s %s " TIME_T_FMT,
870 parv[0], chptr->chname, modebuf, parabuf,
871 (badop == 4) ? (time_t) 0 : chptr->creationtime);
872 sendto_highprot_butone(cptr, 10, ":%s MODE %s %s %s " TIME_T_FMT,
873 parv[0], chptr->chname, modebuf, nparabuf,
874 (badop == 4) ? (time_t) 0 : chptr->creationtime);
879 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s %s",
880 parv[0], chptr->chname, modebuf, parabuf);
881 sendto_highprot_butone(cptr, 10, ":%s MODE %s %s %s",
882 parv[0], chptr->chname, modebuf, nparabuf);
888 static int DoesOp(char *modebuf)
890 modebuf--; /* Is it possible that a mode
891 starts with o and not +o ? */
893 if (*modebuf == 'o' || *modebuf == 'v')
898 /* This function should be removed when all servers are 2.10 */
899 static void sendmodeto_one(aClient *cptr, char *from, char *name,
900 char *mode, char *param, time_t creationtime)
902 if (IsServer(cptr) && DoesOp(mode) && creationtime)
903 sendto_one(cptr, ":%s MODE %s %s %s " TIME_T_FMT,
904 from, name, mode, param, creationtime);
906 sendto_one(cptr, ":%s MODE %s %s %s", from, name, mode, param);
912 * by Carlo Wood (Run), 05 Oct 1998.
916 * When the nick is longer then NICKLEN, it is cut off (its an error of course).
917 * When the user name or host name are too long (USERLEN and HOSTLEN
918 * respectively) then they are cut off at the start with a '*'.
920 * The following transformations are made:
923 * 2) xxx.xxx -> *!*@host
924 * 3) xxx!yyy -> nick!user@*
925 * 4) xxx@yyy -> *!user@host
926 * 5) xxx!yyy@zzz -> nick!user@host
928 char *pretty_mask(char *mask)
930 static char star[2] = { '*', 0 };
931 char *last_dot = NULL;
934 /* Case 1: default */
939 /* Do a _single_ pass through the characters of the mask: */
940 for (ptr = mask; *ptr; ++ptr)
944 /* Case 3 or 5: Found first '!' (without finding a '@' yet) */
948 else if (*ptr == '@')
950 /* Case 4: Found last '@' (without finding a '!' yet) */
955 else if (*ptr == '.')
957 /* Case 2: Found last '.' (without finding a '!' or '@' yet) */
967 /* Case 4 or 5: Found last '@' */
973 if (user == star && last_dot)
983 char *nick_end = (user != star) ? user - 1 : ptr;
984 if (nick_end - nick > NICKLEN)
990 char *user_end = (host != star) ? host - 1 : ptr;
991 if (user_end - user > USERLEN)
993 user = user_end - USERLEN;
998 if (host != star && ptr - host > HOSTLEN)
1000 host = ptr - HOSTLEN;
1003 return make_nick_user_host(nick, user, host);
1006 static char bmodebuf[MODEBUFLEN], bparambuf[MODEBUFLEN];
1007 static char nbparambuf[MODEBUFLEN]; /* "Numeric" Bounce Parameter Buffer */
1010 * Check and try to apply the channel modes passed in the parv array for
1011 * the client ccptr to channel chptr. The resultant changes are printed
1012 * into mbuf and pbuf (if any) and applied to the channel.
1014 static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr, int parc,
1015 char *parv[], char *mbuf, char *pbuf, char *npbuf, int *badop)
1017 static Link chops[MAXPARA - 2]; /* This size is only needed when a broken
1018 server sends more then MAXMODEPARAMS
1020 static int flags[] = {
1021 MODE_PRIVATE, 'p', MODE_SECRET, 's',
1022 MODE_MODERATED, 'm', MODE_NOPRIVMSGS, 'n',
1023 MODE_TOPICLIMIT, 't', MODE_INVITEONLY, 'i',
1024 MODE_VOICE, 'v', MODE_KEY, 'k',
1029 Reg2 char *curr = parv[0], *cp = NULL;
1031 Link *member, *tmp = NULL;
1032 unsigned int whatt = MODE_ADD, bwhatt = 0;
1033 int limitset = 0, bounce, add_banid_called = 0;
1034 size_t len, nlen, blen, nblen;
1036 unsigned int nusers = 0, newmode;
1037 int opcnt = 0, banlsent = 0;
1038 int doesdeop = 0, doesop = 0, hacknotice = 0, change, gotts = 0;
1041 static char numeric[16];
1042 char *bmbuf = bmodebuf, *bpbuf = bparambuf, *nbpbuf = nbparambuf;
1043 time_t newtime = (time_t) 0;
1046 *mbuf = *pbuf = *npbuf = *bmbuf = *bpbuf = *nbpbuf = '\0';
1051 mode = &(chptr->mode);
1052 memcpy(&oldm, mode, sizeof(Mode));
1054 * Mode is accepted when sptr is a channel operator
1055 * but also when the mode is received from a server.
1056 * At this point, let any member pass, so they are allowed
1059 if (!(IsServer(cptr) || (tmp = IsMember(sptr, chptr))))
1062 #ifdef OPER_MODE_LCHAN
1063 if (IsOperOnLocalChannel(sptr, chptr->chname) && !(tmp->flags & CHFL_CHANOP))
1064 LocalChanOperMode = 1;
1067 newmode = mode->mode;
1069 while (curr && *curr)
1084 if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1087 * Check for nickname changes and try to follow these
1088 * to make sure the right client is affected by the
1090 * Even if we find a nick with find_chasing() there
1091 * is still a reason to ignore in a special case.
1092 * We need to ignore the mode when:
1093 * - It is part of a net.burst (from a server and
1094 * a MODE_ADD). Ofcourse we don't ignore mode
1095 * changes from Uworld.
1096 * - The found nick is not on the right side off
1098 * This fixes the bug that when someone (tries to)
1099 * ride a net.break and does so with the nick of
1100 * someone on the otherside, that he is nick collided
1101 * (killed) but his +o still ops the other person.
1103 if (MyUser(sptr) || Protocol(cptr) < 10)
1105 if (!(who = find_chasing(sptr, parv[0], NULL)))
1110 if (!(who = findNUser(parv[0])))
1113 if (whatt == MODE_ADD && IsServer(sptr) && who->from != sptr->from &&
1114 !find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))
1116 if (!(member = find_user_link(chptr->members, who)) ||
1117 (MyUser(sptr) && (member->flags & CHFL_ZOMBIE)))
1119 sendto_one(cptr, err_str(ERR_USERNOTINCHANNEL),
1120 me.name, cptr->name, who->name, chptr->chname);
1123 /* if the user is +k, prevent a deop from local user */
1124 if (whatt == MODE_DEL && IsChannelService(who) &&
1125 MyUser(cptr) && *curr == 'o')
1127 sendto_one(cptr, err_str(ERR_ISCHANSERVICE), me.name,
1128 cptr->name, parv[0], chptr->chname);
1131 #ifdef NO_OPER_DEOP_LCHAN
1133 * if the user is an oper on a local channel, prevent him
1134 * from being deoped. that oper can deop himself though.
1136 if (whatt == MODE_DEL && IsOperOnLocalChannel(who, chptr->chname) &&
1137 (who != sptr) && MyUser(cptr) && *curr == 'o')
1139 sendto_one(cptr, err_str(ERR_ISOPERLCHAN), me.name,
1140 cptr->name, parv[0], chptr->chname);
1144 if (whatt == MODE_ADD)
1146 lp = &chops[opcnt++];
1147 lp->value.cptr = who;
1148 if (IsServer(sptr) && (!(who->flags & FLAGS_TS8) || ((*curr == 'o') &&
1149 !(member->flags & (CHFL_SERVOPOK | CHFL_CHANOP)))))
1150 *badop = ((member->flags & CHFL_DEOPPED) && (*curr == 'o')) ? 2 : 3;
1151 lp->flags = (*curr == 'o') ? MODE_CHANOP : MODE_VOICE;
1152 lp->flags |= MODE_ADD;
1154 else if (whatt == MODE_DEL)
1156 lp = &chops[opcnt++];
1157 lp->value.cptr = who;
1158 doesdeop = 1; /* Also when -v */
1159 lp->flags = (*curr == 'o') ? MODE_CHANOP : MODE_VOICE;
1160 lp->flags |= MODE_DEL;
1169 /* check now so we eat the parameter if present */
1174 char *s = &(*parv)[-1];
1175 unsigned short count = KEYLEN + 1;
1177 while (*++s > ' ' && *s != ':' && --count);
1179 if (!**parv) /* nothing left in key */
1182 if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1184 if (whatt == MODE_ADD)
1186 if (*mode->key && !IsServer(cptr))
1187 sendto_one(cptr, err_str(ERR_KEYSET),
1188 me.name, cptr->name, chptr->chname);
1189 else if (!*mode->key || IsServer(cptr))
1191 lp = &chops[opcnt++];
1192 lp->value.cp = *parv;
1193 if (strlen(lp->value.cp) > (size_t)KEYLEN)
1194 lp->value.cp[KEYLEN] = '\0';
1195 lp->flags = MODE_KEY | MODE_ADD;
1199 else if (whatt == MODE_DEL)
1201 if (strCasediff(mode->key, *parv) == 0 || IsServer(cptr))
1203 lp = &chops[opcnt++];
1204 lp->value.cp = mode->key;
1205 lp->flags = MODE_KEY | MODE_DEL;
1213 if (banlsent) /* Only send it once */
1215 for (lp = chptr->banlist; lp; lp = lp->next)
1216 sendto_one(cptr, rpl_str(RPL_BANLIST), me.name, cptr->name,
1217 chptr->chname, lp->value.ban.banstr, lp->value.ban.who,
1218 lp->value.ban.when);
1219 sendto_one(cptr, rpl_str(RPL_ENDOFBANLIST), me.name, cptr->name,
1229 if ((cp = strchr(*parv, ' ')))
1231 if (opcnt >= MAXMODEPARAMS || **parv == ':' || **parv == '\0')
1234 if (whatt == MODE_ADD)
1236 lp = &chops[opcnt++];
1237 lp->value.cp = *parv;
1238 lp->flags = MODE_ADD | MODE_BAN;
1240 else if (whatt == MODE_DEL)
1242 lp = &chops[opcnt++];
1243 lp->value.cp = *parv;
1244 lp->flags = MODE_DEL | MODE_BAN;
1249 * limit 'l' to only *1* change per mode command but
1254 if (whatt == MODE_ADD && --parc > 0)
1258 if (whatt == MODE_DEL)
1268 if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1270 if (!(nusers = atoi(*++parv)))
1272 lp = &chops[opcnt++];
1273 lp->flags = MODE_ADD | MODE_LIMIT;
1277 sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS),
1278 me.name, cptr->name, "MODE +l");
1280 case 'i': /* falls through for default case */
1281 if (whatt == MODE_DEL)
1282 while ((lp = chptr->invites))
1283 del_invite(lp->value.cptr, chptr);
1285 for (ip = flags; *ip; ip += 2)
1286 if (*(ip + 1) == *curr)
1291 if (whatt == MODE_ADD)
1293 if (*ip == MODE_PRIVATE)
1294 newmode &= ~MODE_SECRET;
1295 else if (*ip == MODE_SECRET)
1296 newmode &= ~MODE_PRIVATE;
1302 else if (!IsServer(cptr))
1303 sendto_one(cptr, err_str(ERR_UNKNOWNMODE),
1304 me.name, cptr->name, *curr);
1309 * Make sure mode strings such as "+m +t +p +i" are parsed
1312 if (!*curr && parc > 0)
1316 /* If this was from a server, and it is the last
1317 * parameter and it starts with a digit, it must
1318 * be the creationtime. --Run
1322 if (parc == 1 && isDigit(*curr))
1324 newtime = atoi(curr);
1325 if (newtime && chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
1327 chptr->creationtime = newtime;
1336 else if (newtime > chptr->creationtime)
1337 { /* It is a net-break ride if we have ops.
1338 bounce modes if we have ops. --Run */
1341 else if (chptr->creationtime == 0)
1343 if (chptr->creationtime == 0 || doesop)
1344 chptr->creationtime = newtime;
1352 * A legal *badop can occur when two
1353 * people join simultaneously a channel,
1354 * Allow for 10 min of lag (and thus hacking
1355 * on channels younger then 10 min) --Run
1357 else if (*badop == 0 ||
1358 chptr->creationtime > (TStime() - TS_LAG_TIME))
1360 if (newtime < chptr->creationtime)
1361 chptr->creationtime = newtime;
1370 } /* end of while loop for MODE processing */
1373 * Now reject non chan ops. Accept modes from opers on local channels
1374 * even if they are deopped
1376 #ifdef OPER_MODE_LCHAN
1377 if (!IsServer(cptr) &&
1378 (!tmp || !((tmp->flags & CHFL_CHANOP) ||
1379 IsOperOnLocalChannel(sptr, chptr->chname))))
1381 if (!IsServer(cptr) && (!tmp || !(tmp->flags & CHFL_CHANOP)))
1385 return (opcnt || newmode != mode->mode || limitset || keychange) ? 0 : -1;
1388 if (doesop && newtime == 0 && IsServer(sptr))
1392 (aconf = find_conf_host(cptr->confs, sptr->name, CONF_UWORLD)))
1395 #ifdef OPER_MODE_LCHAN
1396 bounce = (*badop == 1 || *badop == 2 ||
1397 (is_deopped(sptr, chptr) &&
1398 !IsOperOnLocalChannel(sptr, chptr->chname))) ? 1 : 0;
1400 bounce = (*badop == 1 || *badop == 2 || is_deopped(sptr, chptr)) ? 1 : 0;
1404 for (ip = flags; *ip; ip += 2)
1405 if ((*ip & newmode) && !(*ip & oldm.mode))
1409 if (bwhatt != MODE_DEL)
1414 *bmbuf++ = *(ip + 1);
1418 if (whatt != MODE_ADD)
1424 *mbuf++ = *(ip + 1);
1428 for (ip = flags; *ip; ip += 2)
1429 if ((*ip & oldm.mode) && !(*ip & newmode))
1433 if (bwhatt != MODE_ADD)
1438 *bmbuf++ = *(ip + 1);
1442 if (whatt != MODE_DEL)
1448 *mbuf++ = *(ip + 1);
1453 if (limitset && !nusers && mode->limit)
1457 if (bwhatt != MODE_ADD)
1463 sprintf(numeric, "%-15d", mode->limit);
1464 if ((cp = strchr(numeric, ' ')))
1466 strcat(bpbuf, numeric);
1467 blen += strlen(numeric);
1469 strcat(nbpbuf, numeric);
1470 nblen += strlen(numeric);
1471 strcat(nbpbuf, " ");
1475 if (whatt != MODE_DEL)
1480 mode->mode &= ~MODE_LIMIT;
1486 * Reconstruct "+bkov" chain.
1492 unsigned int prev_whatt = 0;
1494 for (; i < opcnt; i++)
1498 * make sure we have correct mode change sign
1500 if (whatt != (lp->flags & (MODE_ADD | MODE_DEL)))
1502 if (lp->flags & MODE_ADD)
1516 nlen = strlen(npbuf);
1518 * get c as the mode char and tmp as a pointer to
1519 * the parameter for this mode change.
1521 switch (lp->flags & MODE_WPARAS)
1525 cp = lp->value.cptr->name;
1529 cp = lp->value.cptr->name;
1533 * I made this a bit more user-friendly (tm):
1535 * nick!user = nick!user@*
1536 * user@host = *!user@host
1537 * host.name = *!*@host.name --Run
1540 cp = pretty_mask(lp->value.cp);
1548 sprintf(numeric, "%-15d", nusers);
1549 if ((cp = strchr(numeric, ' ')))
1555 /* What could be added: cp+' '+' '+<TS>+'\0' */
1556 if (len + strlen(cp) + 13 > (size_t)MODEBUFLEN ||
1557 nlen + strlen(cp) + NUMNICKLEN + 12 > (size_t)MODEBUFLEN)
1560 switch (lp->flags & MODE_WPARAS)
1563 if (strlen(cp) > (size_t)KEYLEN)
1564 *(cp + KEYLEN) = '\0';
1565 if ((whatt == MODE_ADD && (*mode->key == '\0' ||
1566 strCasediff(mode->key, cp) != 0)) ||
1567 (whatt == MODE_DEL && (*mode->key != '\0')))
1571 if (*mode->key == '\0')
1573 if (bwhatt != MODE_DEL)
1583 nblen += strlen(cp);
1584 strcat(nbpbuf, " ");
1589 if (bwhatt != MODE_ADD)
1594 strcat(bpbuf, mode->key);
1595 blen += strlen(mode->key);
1598 strcat(nbpbuf, mode->key);
1599 nblen += strlen(mode->key);
1600 strcat(nbpbuf, " ");
1605 if (*mbuf != '+' && *mbuf != '-')
1621 if (whatt == MODE_ADD)
1622 strncpy(mode->key, cp, KEYLEN);
1629 if (nusers && nusers != mode->limit)
1633 if (mode->limit == 0)
1635 if (bwhatt != MODE_DEL)
1643 if (bwhatt != MODE_ADD)
1648 sprintf(numeric, "%-15d", mode->limit);
1649 if ((cp = strchr(numeric, ' ')))
1651 strcat(bpbuf, numeric);
1652 blen += strlen(numeric);
1655 strcat(nbpbuf, numeric);
1656 nblen += strlen(numeric);
1657 strcat(nbpbuf, " ");
1662 if (*mbuf != '+' && *mbuf != '-')
1678 mode->limit = nusers;
1684 tmp = find_user_link(chptr->members, lp->value.cptr);
1685 if (lp->flags & MODE_ADD)
1687 change = (~tmp->flags) & CHFL_OVERLAP & lp->flags;
1688 if (change && bounce)
1690 if (lp->flags & MODE_CHANOP)
1691 tmp->flags |= CHFL_DEOPPED;
1692 if (bwhatt != MODE_DEL)
1698 strcat(bpbuf, lp->value.cptr->name);
1699 blen += strlen(lp->value.cptr->name);
1702 sprintf_irc(nbpbuf + nblen, "%s%s ", NumNick(lp->value.cptr));
1703 nblen += strlen(nbpbuf + nblen);
1708 tmp->flags |= lp->flags & CHFL_OVERLAP;
1709 if (lp->flags & MODE_CHANOP)
1711 tmp->flags &= ~CHFL_DEOPPED;
1713 tmp->flags &= ~CHFL_SERVOPOK;
1719 change = tmp->flags & CHFL_OVERLAP & lp->flags;
1720 if (change && bounce)
1722 if (lp->flags & MODE_CHANOP)
1723 tmp->flags &= ~CHFL_DEOPPED;
1724 if (bwhatt != MODE_ADD)
1730 strcat(bpbuf, lp->value.cptr->name);
1731 blen += strlen(lp->value.cptr->name);
1734 sprintf_irc(nbpbuf + nblen, "%s%s ", NumNick(lp->value.cptr));
1735 blen += strlen(bpbuf + blen);
1740 tmp->flags &= ~change;
1741 if ((change & MODE_CHANOP) && IsServer(sptr))
1742 tmp->flags |= CHFL_DEOPPED;
1745 if (change || *badop == 2 || *badop == 4)
1752 sprintf_irc(npbuf + nlen, "%s%s ", NumNick(lp->value.cptr));
1753 nlen += strlen(npbuf + nlen);
1754 npbuf[nlen++] = ' ';
1760 if (*mbuf != '+' && *mbuf != '-')
1768 * Only bans aren't bounced, it makes no sense to bounce last second
1769 * bans while propagating bans done before the net.rejoin. The reason
1770 * why I don't bounce net.rejoin bans is because it is too much
1771 * work to take care of too long strings adding the necessary TS to
1772 * net.burst bans -- RunLazy
1773 * We do have to check for *badop==2 now, we don't want HACKs to take
1776 * Since BURST - I *did* implement net.rejoin ban bouncing. So now it
1777 * certainly makes sense to also bounce 'last second' bans (bans done
1778 * after the net.junction). -- RunHardWorker
1780 if ((change = (whatt & MODE_ADD) &&
1781 !add_banid(sptr, chptr, cp, !bounce, !add_banid_called)))
1782 add_banid_called = 1;
1784 change = (whatt & MODE_DEL) && !del_banid(chptr, cp, !bounce);
1786 if (bounce && change)
1789 if ((whatt & MODE_ADD))
1791 if (bwhatt != MODE_DEL)
1797 else if ((whatt & MODE_DEL))
1799 if (bwhatt != MODE_ADD)
1811 nblen += strlen(cp);
1812 strcat(nbpbuf, " ");
1830 if (*mbuf != '+' && *mbuf != '-')
1837 } /* for (; i < opcnt; i++) */
1844 if (!hacknotice && *bmodebuf && chptr->creationtime)
1846 if (Protocol(cptr) < 10)
1847 sendto_one(cptr, ":%s MODE %s %s %s " TIME_T_FMT,
1848 me.name, chptr->chname, bmodebuf, bparambuf,
1849 *badop == 2 ? (time_t) 0 : chptr->creationtime);
1851 sendto_one(cptr, "%s MODE %s %s %s " TIME_T_FMT,
1852 NumServ(&me), chptr->chname, bmodebuf, nbparambuf,
1853 *badop == 2 ? (time_t) 0 : chptr->creationtime);
1855 /* If there are possibly bans to re-add, bounce them now */
1856 if (add_banid_called && bounce)
1858 Link *ban[6]; /* Max 6 bans at a time */
1859 size_t len[6], sblen, total_len;
1860 int cnt, delayed = 0;
1861 while (delayed || (ban[0] = next_overlapped_ban()))
1863 len[0] = strlen(ban[0]->value.ban.banstr);
1864 cnt = 1; /* We already got one ban :) */
1865 sblen = sprintf_irc(sendbuf, ":%s MODE %s +b",
1866 me.name, chptr->chname) - sendbuf;
1867 total_len = sblen + 1 + len[0]; /* 1 = ' ' */
1868 /* Find more bans: */
1870 while (cnt < 6 && (ban[cnt] = next_overlapped_ban()))
1872 len[cnt] = strlen(ban[cnt]->value.ban.banstr);
1873 if (total_len + 5 + len[cnt] > BUFSIZE) /* 5 = "b \r\n\0" */
1875 delayed = cnt + 1; /* != 0 */
1878 sendbuf[sblen++] = 'b';
1879 total_len += 2 + len[cnt++]; /* 2 = "b " */
1883 sendbuf[sblen++] = ' ';
1884 strcpy(sendbuf + sblen, ban[cnt]->value.ban.banstr);
1887 sendbufto_one(cptr); /* Send bounce to uplink */
1889 ban[0] = ban[delayed - 1];
1892 /* Send -b's of overlapped bans to clients to keep them synchronized */
1893 if (add_banid_called && !bounce)
1896 char *banstr[6]; /* Max 6 bans at a time */
1897 size_t len[6], sblen, psblen, total_len;
1898 int cnt, delayed = 0;
1902 psblen = sprintf_irc(sendbuf, ":%s MODE %s -b",
1903 sptr->name, chptr->chname) - sendbuf;
1904 else /* We rely on IsRegistered(sptr) being true for MODE */
1905 psblen = sprintf_irc(sendbuf, ":%s!%s@%s MODE %s -b", sptr->name,
1906 sptr->user->username, sptr->user->host, chptr->chname) - sendbuf;
1907 while (delayed || (ban = next_removed_overlapped_ban()))
1911 len[0] = strlen((banstr[0] = ban->value.ban.banstr));
1912 ban->value.ban.banstr = NULL;
1914 cnt = 1; /* We already got one ban :) */
1916 total_len = sblen + 1 + len[0]; /* 1 = ' ' */
1917 /* Find more bans: */
1919 while (cnt < 6 && (ban = next_removed_overlapped_ban()))
1921 len[cnt] = strlen((banstr[cnt] = ban->value.ban.banstr));
1922 ban->value.ban.banstr = NULL;
1923 if (total_len + 5 + len[cnt] > BUFSIZE) /* 5 = "b \r\n\0" */
1925 delayed = cnt + 1; /* != 0 */
1928 sendbuf[sblen++] = 'b';
1929 total_len += 2 + len[cnt++]; /* 2 = "b " */
1933 sendbuf[sblen++] = ' ';
1934 strcpy(sendbuf + sblen, banstr[cnt]);
1935 RunFree(banstr[cnt]);
1938 for (lp = chptr->members; lp; lp = lp->next)
1939 if (MyConnect(acptr = lp->value.cptr) && !(lp->flags & CHFL_ZOMBIE))
1940 sendbufto_one(acptr);
1943 banstr[0] = banstr[delayed - 1];
1944 len[0] = len[delayed - 1];
1949 return gotts ? 1 : -1;
1952 /* We are now treating the <key> part of /join <channel list> <key> as a key
1953 * ring; that is, we try one key against the actual channel key, and if that
1954 * doesn't work, we try the next one, and so on. -Kev -Texaco
1955 * Returns: 0 on match, 1 otherwise
1956 * This version contributed by SeKs <intru@info.polymtl.ca>
1958 static int compall(char *key, char *keyring)
1963 p1 = key; /* point to the key... */
1964 while (*p1 && *p1 == *keyring)
1965 { /* step through the key and ring until they
1971 if (!*p1 && (!*keyring || *keyring == ','))
1972 /* ok, if we're at the end of the and also at the end of one of the keys
1973 in the keyring, we have a match */
1976 if (!*keyring) /* if we're at the end of the key ring, there
1977 weren't any matches, so we return 1 */
1980 /* Not at the end of the key ring, so step
1981 through to the next key in the ring: */
1982 while (*keyring && *(keyring++) != ',');
1984 goto top; /* and check it against the key */
1987 static int can_join(aClient *sptr, aChannel *chptr, char *key)
1990 int overrideJoin = 0;
1992 #ifdef OPER_WALK_THROUGH_LMODES
1993 /* An oper can force a join on a local channel using "OVERRIDE" as the key.
1994 a HACK(4) notice will be sent if he would not have been supposed
1995 to join normally. */
1996 if (IsOperOnLocalChannel(sptr,chptr->chname) && !BadPtr(key) &&
1997 compall("OVERRIDE",key) == 0)
1998 overrideJoin = MAGIC_OPER_OVERRIDE;
2001 * Now a banned user CAN join if invited -- Nemesi
2002 * Now a user CAN escape channel limit if invited -- bfriendly
2004 if ((chptr->mode.mode & MODE_INVITEONLY) || (is_banned(sptr, chptr, NULL)
2005 || (chptr->mode.limit && chptr->users >= chptr->mode.limit)))
2007 for (lp = sptr->user->invited; lp; lp = lp->next)
2008 if (lp->value.chptr == chptr)
2012 if (chptr->mode.limit && chptr->users >= chptr->mode.limit)
2013 return (overrideJoin + ERR_CHANNELISFULL);
2015 * This can return an "Invite only" msg instead of the "You are banned"
2016 * if _both_ conditions are true, but who can say what is more
2017 * appropriate ? checking again IsBanned would be _SO_ cpu-xpensive !
2019 return overrideJoin + ((chptr->mode.mode & MODE_INVITEONLY) ?
2020 ERR_INVITEONLYCHAN : ERR_BANNEDFROMCHAN);
2024 /* now using compall (above) to test against a whole key ring -Kev */
2025 if (*chptr->mode.key && (BadPtr(key) || compall(chptr->mode.key, key)))
2026 return overrideJoin + (ERR_BADCHANNELKEY);
2032 * Remove bells and commas from channel name
2035 static void clean_channelname(char *cn)
2050 /* Missed the Icelandic letter ETH last time: */
2051 if ((unsigned char)(*cn) == 0xd0)
2059 * Get Channel block for i (and allocate a new channel
2060 * block, if it didn't exists before).
2062 static aChannel *get_channel(aClient *cptr, char *chname, int flag)
2064 Reg1 aChannel *chptr;
2070 len = strlen(chname);
2071 if (MyUser(cptr) && len > CHANNELLEN)
2074 *(chname + CHANNELLEN) = '\0';
2076 if ((chptr = FindChannel(chname)))
2080 chptr = (aChannel *)RunMalloc(sizeof(aChannel) + len);
2082 memset(chptr, 0, sizeof(aChannel));
2083 strcpy(chptr->chname, chname);
2085 channel->prevch = chptr;
2086 chptr->prevch = NULL;
2087 chptr->nextch = channel;
2088 chptr->creationtime = MyUser(cptr) ? TStime() : (time_t) 0;
2095 static void add_invite(aClient *cptr, aChannel *chptr)
2097 Reg1 Link *inv, **tmp;
2099 del_invite(cptr, chptr);
2101 * Delete last link in chain if the list is max length
2103 if (list_length(cptr->user->invited) >= MAXCHANNELSPERUSER)
2104 del_invite(cptr, cptr->user->invited->value.chptr);
2106 * Add client to channel invite list
2109 inv->value.cptr = cptr;
2110 inv->next = chptr->invites;
2111 chptr->invites = inv;
2113 * Add channel to the end of the client invite list
2115 for (tmp = &(cptr->user->invited); *tmp; tmp = &((*tmp)->next));
2117 inv->value.chptr = chptr;
2123 * Delete Invite block from channel invite list and client invite list
2125 void del_invite(aClient *cptr, aChannel *chptr)
2127 Reg1 Link **inv, *tmp;
2129 for (inv = &(chptr->invites); (tmp = *inv); inv = &tmp->next)
2130 if (tmp->value.cptr == cptr)
2137 for (inv = &(cptr->user->invited); (tmp = *inv); inv = &tmp->next)
2138 if (tmp->value.chptr == chptr)
2146 /* List and skip all channels that are listen */
2147 void list_next_channels(aClient *cptr, int nr)
2149 aListingArgs *args = cptr->listing;
2150 aChannel *chptr = args->chptr;
2151 chptr->mode.mode &= ~MODE_LISTED;
2152 while (is_listed(chptr) || --nr >= 0)
2154 for (; chptr; chptr = chptr->nextch)
2156 if (!cptr->user || (SecretChannel(chptr) && !IsMember(cptr, chptr)))
2158 if (chptr->users > args->min_users && chptr->users < args->max_users &&
2159 chptr->creationtime > args->min_time &&
2160 chptr->creationtime < args->max_time &&
2161 (!args->topic_limits || (*chptr->topic &&
2162 chptr->topic_time > args->min_topic_time &&
2163 chptr->topic_time < args->max_topic_time)))
2165 sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name,
2166 ShowChannel(cptr, chptr) ? chptr->chname : "*",
2167 chptr->users, ShowChannel(cptr, chptr) ? chptr->topic : "");
2168 chptr = chptr->nextch;
2174 RunFree(cptr->listing);
2175 cptr->listing = NULL;
2176 sendto_one(cptr, rpl_str(RPL_LISTEND), me.name, cptr->name);
2182 cptr->listing->chptr = chptr;
2183 chptr->mode.mode |= MODE_LISTED;
2188 * Subtract one user from channel i (and free channel
2189 * block, if channel became empty).
2191 static void sub1_from_channel(aChannel *chptr)
2196 if (chptr->users > 1) /* Can be 0, called for an empty channel too */
2202 /* Channel became (or was) empty: Remove channel */
2203 if (is_listed(chptr))
2206 for (i = 0; i <= highest_fd; i++)
2209 if ((acptr = loc_clients[i]) && acptr->listing &&
2210 acptr->listing->chptr == chptr)
2212 list_next_channels(acptr, 1);
2213 break; /* Only one client can list a channel */
2218 * Now, find all invite links from channel structure
2220 while ((tmp = chptr->invites))
2221 del_invite(tmp->value.cptr, chptr);
2223 tmp = chptr->banlist;
2228 RunFree(obtmp->value.ban.banstr);
2229 RunFree(obtmp->value.ban.who);
2233 chptr->prevch->nextch = chptr->nextch;
2235 channel = chptr->nextch;
2237 chptr->nextch->prevch = chptr->prevch;
2240 RunFree((char *)chptr);
2246 * parv[0] = sender prefix
2248 * parv[2] = channel keys (client), or channel TS (server)
2250 int m_join(aClient *cptr, aClient *sptr, int parc, char *parv[])
2252 static char jbuf[BUFSIZE], mbuf[BUFSIZE];
2254 Reg3 aChannel *chptr;
2255 Reg4 char *name, *keysOrTS = NULL;
2256 int i = 0, zombie = 0, sendcreate = 0;
2257 unsigned int flags = 0;
2258 size_t jlen = 0, mlen = 0;
2260 char *p = NULL, *bufptr;
2262 if (parc < 2 || *parv[1] == '\0')
2264 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "JOIN");
2268 for (p = parv[1]; *p; p++) /* find the last "JOIN 0" in the line -Kev */
2270 && (*(p + 1) == ',' || *(p + 1) == '\0' || !isIrcCh(*(p + 1))))
2272 /* If it's a single "0", remember the place; we will start parsing
2273 the channels after the last 0 in the line -Kev */
2280 { /* Step through to the next comma or until the
2281 end of the line, in an attempt to save CPU
2283 while (*p != ',' && *p != '\0')
2289 keysOrTS = parv[2]; /* Remember where our keys are or the TS is;
2290 parv[2] needs to be NULL for the call to
2291 m_names below -Kev */
2294 *jbuf = *mbuf = '\0'; /* clear both join and mode buffers -Kev */
2296 * Rebuild list of channels joined to be the actual result of the
2297 * JOIN. Note that "JOIN 0" is the destructive problem.
2299 for (name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ","))
2302 if (MyConnect(sptr))
2303 clean_channelname(name);
2304 else if (IsLocalChannel(name))
2306 if (*name == '0' && *(name + 1) == '\0')
2308 /* Remove the user from all his channels -Kev */
2309 while ((lp = sptr->user->channel))
2311 chptr = lp->value.chptr;
2312 if (!is_zombie(sptr, chptr))
2313 sendto_channel_butserv(chptr, sptr, PartFmt2,
2314 parv[0], chptr->chname, "Left all channels");
2315 remove_user_from_channel(sptr, chptr);
2318 *mbuf = *jbuf = '\0';
2322 { /* not a /join 0, so treat it as
2323 a /join #channel -Kev */
2324 if (!IsChannelName(name))
2327 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
2331 if (MyConnect(sptr))
2334 if(bad_channel(name) && !IsAnOper(sptr))
2336 sendto_one(sptr, err_str(ERR_BADCHANNAME), me.name, parv[0],name);
2342 * Local client is first to enter previously nonexistant
2343 * channel so make them (rightfully) the Channel Operator.
2344 * This looks kind of ugly because we try to avoid calling the strlen()
2346 if (ChannelExists(name))
2348 flags = CHFL_DEOPPED;
2351 else if (strlen(name) > CHANNELLEN)
2353 *(name + CHANNELLEN) = '\0';
2354 if (ChannelExists(name))
2356 flags = CHFL_DEOPPED;
2361 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
2367 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
2371 #ifdef OPER_NO_CHAN_LIMIT
2373 * Opers are allowed to join any number of channels
2375 if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsAnOper(sptr))
2377 if (sptr->user->joined >= MAXCHANNELSPERUSER)
2380 chptr = get_channel(sptr, name, !CREATE);
2381 sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
2382 me.name, parv[0], chptr ? chptr->chname : name);
2383 break; /* Can't return, else he won't get on ANY
2384 channels! Break out of the for loop instead.
2388 chptr = get_channel(sptr, name, CREATE);
2389 if (chptr && (lp = find_user_link(chptr->members, sptr)))
2391 if (lp->flags & CHFL_ZOMBIE)
2394 flags = lp->flags & (CHFL_DEOPPED | CHFL_SERVOPOK);
2395 remove_user_from_channel(sptr, chptr);
2396 chptr = get_channel(sptr, name, CREATE);
2401 name = chptr->chname;
2402 if (!chptr->creationtime) /* A remote JOIN created this channel ? */
2403 chptr->creationtime = MAGIC_REMOTE_JOIN_TS;
2406 if (chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
2407 chptr->creationtime = atoi(keysOrTS);
2409 parc = 2; /* Don't pass it on */
2413 if (!MyConnect(sptr))
2414 flags = CHFL_DEOPPED;
2415 if (sptr->flags & FLAGS_TS8)
2416 flags |= CHFL_SERVOPOK;
2418 if (MyConnect(sptr))
2420 int created = chptr->users == 0;
2421 if (check_target_limit(sptr, chptr, chptr->chname, created))
2423 if (created) /* Did we create the channel? */
2424 sub1_from_channel(chptr); /* Remove it again! */
2427 if ((i = can_join(sptr, chptr, keysOrTS)))
2429 #ifdef OPER_WALK_THROUGH_LMODES
2430 if (i > MAGIC_OPER_OVERRIDE)
2432 switch(i - MAGIC_OPER_OVERRIDE)
2434 case ERR_CHANNELISFULL: i = 'l'; break;
2435 case ERR_INVITEONLYCHAN: i = 'i'; break;
2436 case ERR_BANNEDFROMCHAN: i = 'b'; break;
2437 case ERR_BADCHANNELKEY: i = 'k'; break;
2439 sendto_op_mask(SNO_HACK4,"OPER JOIN: %s JOIN %s (overriding +%c)",sptr->name,chptr->chname,i);
2443 sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
2447 sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
2453 * Complete user entry to the new channel (if any)
2455 add_user_to_channel(chptr, sptr, flags);
2458 * Notify all other users on the new channel
2460 sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
2464 del_invite(sptr, chptr);
2465 if (chptr->topic[0] != '\0')
2467 sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
2468 parv[0], name, chptr->topic);
2469 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0], name,
2470 chptr->topic_nick, chptr->topic_time);
2473 m_names(cptr, sptr, 2, parv);
2477 /* Select proper buffer; mbuf for creation, jbuf otherwise */
2480 continue; /* Head off local channels at the pass */
2482 bufptr = (sendcreate == 0) ? jbuf : mbuf;
2483 buflen = (sendcreate == 0) ? &jlen : &mlen;
2485 if (*buflen < BUFSIZE - len - 2)
2489 strcat(bufptr, ","); /* Add to join buf */
2492 strncat(bufptr, name, BUFSIZE - *buflen - 1);
2495 sendcreate = 0; /* Reset sendcreate */
2498 #ifndef NO_PROTOCOL9
2499 if (*jbuf || *mbuf) /* Propagate joins to P09 servers */
2500 sendto_lowprot_butone(cptr, 9, (*jbuf && *mbuf) ? ":%s JOIN %s,%s" :
2501 ":%s JOIN %s%s", parv[0], jbuf, mbuf);
2504 if (*jbuf) /* Propgate joins to P10 servers */
2506 sendto_serv_butone(cptr,
2507 parc > 2 ? ":%s JOIN %s %s" : ":%s JOIN %s", parv[0], jbuf, keysOrTS);
2509 sendto_highprot_butone(cptr, 10,
2510 parc > 2 ? ":%s JOIN %s %s" : ":%s JOIN %s", parv[0], jbuf, keysOrTS);
2512 if (*mbuf) /* and now creation events */
2514 sendto_serv_butone(cptr, "%s%s CREATE %s " TIME_T_FMT,
2515 NumNick(sptr), mbuf, TStime());
2517 sendto_highprot_butone(cptr, 10, "%s%s CREATE %s " TIME_T_FMT,
2518 NumNick(sptr), mbuf, TStime());
2522 { /* shouldn't ever set TS for remote JOIN's */
2524 { /* check for channels that need TS's */
2526 for (name = strtoken(&p, jbuf, ","); name; name = strtoken(&p, NULL, ","))
2528 chptr = get_channel(sptr, name, !CREATE);
2529 if (chptr && chptr->mode.mode & MODE_SENDTS)
2531 sendto_serv_butone(cptr, ":%s MODE %s + " TIME_T_FMT, me.name,
2532 chptr->chname, chptr->creationtime); /* ok, send TS */
2533 chptr->mode.mode &= ~MODE_SENDTS; /* reset flag */
2539 { /* ok, send along modes for creation events to P9 */
2541 for (name = strtoken(&p, mbuf, ","); name; name = strtoken(&p, NULL, ","))
2543 chptr = get_channel(sptr, name, !CREATE);
2544 sendto_lowprot_butone(cptr, 9, ":%s MODE %s +o %s " TIME_T_FMT,
2545 me.name, chptr->chname, parv[0], chptr->creationtime);
2555 * parv[0] = sender prefix
2556 * parv[1] = channel channelname
2557 * parv[2] = channel time stamp
2559 * This function does nothing, it does passes DESTRUCT to the other servers.
2560 * In the future we will start to use this message.
2563 int m_destruct(aClient *cptr, aClient *sptr, int parc, char *parv[])
2565 time_t chanTS; /* Creation time of the channel */
2567 if (parc < 3 || *parv[2] == '\0')
2571 /* Allow DESTRUCT from user */
2577 /* sanity checks: Only accept DESTRUCT messages from servers */
2578 if (!IsServer(sptr))
2581 /* Don't pass on DESTRUCT messages for channels that exist */
2582 if (FindChannel(parv[1]))
2585 chanTS = atoi(parv[2]);
2587 /* Pass on DESTRUCT message */
2588 sendto_highprot_butone(cptr, 10, "%s DESTRUCT %s " TIME_T_FMT,
2589 NumServ(sptr), parv[1], chanTS);
2597 * parv[0] = sender prefix
2598 * parv[1] = channel names
2599 * parv[2] = channel time stamp
2601 int m_create(aClient *cptr, aClient *sptr, int parc, char *parv[])
2603 char cbuf[BUFSIZE]; /* Buffer for list with channels
2604 that `sptr' really creates */
2605 time_t chanTS; /* Creation time for all channels
2606 in the comma seperated list */
2608 Reg5 aChannel *chptr;
2611 /* sanity checks: Only accept CREATE messages from servers */
2612 if (!IsServer(cptr) || parc < 3 || *parv[2] == '\0')
2615 chanTS = atoi(parv[2]);
2617 *cbuf = '\0'; /* Start with empty buffer */
2619 /* For each channel in the comma seperated list: */
2620 for (name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ","))
2622 badop = 0; /* Default is to accept the op */
2623 if ((chptr = FindChannel(name)))
2625 name = chptr->chname;
2626 if (TStime() - chanTS > TS_LAG_TIME)
2628 /* A bounce would not be accepted anyway - if we get here something
2629 is wrong with the TS clock syncing (or we have more then
2630 TS_LAG_TIME lag, or an admin is hacking */
2632 /* This causes a HACK notice on all upstream servers: */
2633 if (Protocol(cptr) < 10)
2634 sendto_one(cptr, ":%s MODE %s -o %s 0", me.name, name, sptr->name);
2636 sendto_one(cptr, ":%s MODE %s -o %s%s 0",
2637 me.name, name, NumNick(sptr));
2638 /* This causes a WALLOPS on all downstream servers and a notice to our
2640 parv[1] = name; /* Corrupt parv[1], it is not used anymore anyway */
2641 send_hack_notice(cptr, sptr, parc, parv, badop, 2);
2643 else if (chptr->creationtime && chanTS > chptr->creationtime &&
2644 chptr->creationtime != MAGIC_REMOTE_JOIN_TS)
2646 /* We (try) to bounce the mode, because the CREATE is used on an older
2647 channel, probably a net.ride */
2649 /* Send a deop upstream: */
2650 if (Protocol(cptr) < 10)
2651 sendto_one(cptr, ":%s MODE %s -o %s " TIME_T_FMT, me.name,
2652 name, sptr->name, chptr->creationtime);
2654 sendto_one(cptr, ":%s MODE %s -o %s%s " TIME_T_FMT, me.name,
2655 name, NumNick(sptr), chptr->creationtime);
2658 else /* Channel doesn't exist: create it */
2659 chptr = get_channel(sptr, name, CREATE);
2661 /* Add and mark ops */
2662 add_user_to_channel(chptr, sptr,
2663 (badop || IsModelessChannel(name)) ? CHFL_DEOPPED : CHFL_CHANOP);
2665 /* Send user join to the local clients (if any) */
2666 sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
2668 if (badop) /* handle badop: convert CREATE into JOIN */
2669 sendto_serv_butone(cptr, ":%s JOIN %s " TIME_T_FMT,
2670 sptr->name, name, chptr->creationtime);
2673 /* Send the op to local clients:
2674 (if any; extremely unlikely, but it CAN happen) */
2675 if (!IsModelessChannel(name))
2676 sendto_channel_butserv(chptr, sptr, ":%s MODE %s +o %s",
2677 sptr->user->server->name, name, parv[0]);
2679 /* Set/correct TS and add the channel to the
2680 buffer for accepted channels: */
2681 chptr->creationtime = chanTS;
2688 if (*cbuf) /* Any channel accepted with ops ? */
2691 sendto_serv_butone(cptr, "%s%s CREATE %s " TIME_T_FMT,
2692 NumNick(sptr), cbuf, chanTS);
2694 /* send CREATEs to 2.10 servers */
2695 sendto_highprot_butone(cptr, 10, "%s%s CREATE %s " TIME_T_FMT,
2696 NumNick(sptr), cbuf, chanTS);
2698 /* And JOIN + MODE to 2.9 servers; following
2699 is not needed after all are 2.10 */
2700 sendto_lowprot_butone(cptr, 9, ":%s JOIN %s", parv[0], cbuf);
2702 for (name = strtoken(&p, cbuf, ","); name; name = strtoken(&p, NULL, ","))
2703 sendto_lowprot_butone(cptr, 9, ":%s MODE %s +o %s " TIME_T_FMT,
2704 sptr->user->server->name, name, parv[0], chanTS);
2711 static size_t prefix_len;
2713 static void add_token_to_sendbuf(char *token, size_t *sblenp, int *firstp,
2714 int *send_itp, char is_a_ban, int mode)
2716 int first = *firstp;
2719 * Heh - we do not need to test if it still fits in the buffer, because
2720 * this BURST message is reconstructed from another BURST message, and
2721 * it only can become smaller. --Run
2724 if (*firstp) /* First token in this parameter ? */
2728 *send_itp = 1; /* Buffer contains data to be sent */
2729 sendbuf[(*sblenp)++] = ' ';
2732 sendbuf[(*sblenp)++] = ':'; /* Bans are always the last "parv" */
2733 sendbuf[(*sblenp)++] = is_a_ban;
2736 else /* Of course, 'send_it' is already set here */
2737 /* Seperate banmasks with a space because
2738 they can contain commas themselfs: */
2739 sendbuf[(*sblenp)++] = is_a_ban ? ' ' : ',';
2740 strcpy(sendbuf + *sblenp, token);
2741 *sblenp += strlen(token);
2742 if (!is_a_ban) /* nick list ? Need to take care
2743 of modes for nicks: */
2745 static int last_mode = 0;
2746 mode &= CHFL_CHANOP | CHFL_VOICE;
2749 if (last_mode != mode) /* Append mode like ':ov' if changed */
2752 sendbuf[(*sblenp)++] = ':';
2753 if (mode & CHFL_CHANOP)
2754 sendbuf[(*sblenp)++] = 'o';
2755 if (mode & CHFL_VOICE)
2756 sendbuf[(*sblenp)++] = 'v';
2758 sendbuf[*sblenp] = '\0';
2762 static void cancel_mode(aClient *sptr, aChannel *chptr, char m,
2763 const char *param, int *count)
2765 static char *pb, *sbp, *sbpi;
2766 int paramdoesntfit = 0;
2767 if (*count == -1) /* initialize ? */
2770 sprintf_irc(sendbuf, ":%s MODE %s -", sptr->name, chptr->chname);
2774 /* m == 0 means flush */
2779 size_t nplen = strlen(param);
2780 if (pb - parabuf + nplen + 23 > MODEBUFLEN)
2794 else if (*count == 0)
2796 if (*count == 6 || !m || paramdoesntfit)
2798 #ifndef NO_PROTOCOL9
2803 strcpy(sbp, parabuf);
2804 #ifndef NO_PROTOCOL9
2805 sbe = sbp + strlen(parabuf);
2807 for (member = chptr->members; member; member = member->next)
2808 if (MyUser(member->value.cptr))
2809 sendbufto_one(member->value.cptr);
2810 #ifndef NO_PROTOCOL9
2811 sprintf_irc(sbe, " " TIME_T_FMT, chptr->creationtime);
2812 /* Send 'sendbuf' to all 2.9 downlinks: */
2813 for (lp = me.serv->down; lp; lp = lp->next)
2814 if (Protocol(lp->value.cptr) < 10)
2815 sendbufto_one(lp->value.cptr);
2826 pb += strlen(param);
2832 * m_burst -- by Run carlo@runaway.xs4all.nl december 1995 till march 1997
2834 * parv[0] = sender prefix
2835 * parv[1] = channel name
2836 * parv[2] = channel timestamp
2837 * The meaning of the following parv[]'s depend on their first character:
2838 * If parv[n] starts with a '+':
2839 * Net burst, additive modes
2841 * parv[n+1] = <param> (optional)
2842 * parv[n+2] = <param> (optional)
2843 * If parv[n] starts with a '%', then n will be parc-1:
2844 * parv[n] = %<ban> <ban> <ban> ...
2845 * If parv[n] starts with another character:
2846 * parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
2847 * where <mode> is the channel mode (ov) of nick and all following nicks.
2850 * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
2852 * Anti net.ride code.
2854 * When the channel already exist, and its TS is larger then
2855 * the TS in the BURST message, then we cancel all existing modes.
2856 * If its is smaller then the received BURST message is ignored.
2857 * If it's equal, then the received modes are just added.
2859 int m_burst(aClient *cptr, aClient *sptr, int parc, char *parv[])
2861 Reg1 aChannel *chptr;
2863 int netride = 0, wipeout = 0, n;
2864 int send_it = 0, add_banid_not_called = 1;
2866 size_t sblen, mblen = 0;
2867 int mblen2, pblen2, cnt;
2869 char prev_key[KEYLEN + 1];
2871 #ifndef NO_PROTOCOL9
2875 /* BURST is only for servers and has at least 4 parameters */
2876 if (!IsServer(cptr) || parc < 4)
2883 if (find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))
2886 sprintf_irc(sendbuf,
2887 ":%s NOTICE * :*** Notice -- HACK(4): %s BURST %s %s", me.name,
2888 sptr->name, parv[1], parv[2]);
2889 for (i = 3; i < parc - 1; ++i)
2890 p = sprintf_irc(p, " %s", parv[i]);
2891 sprintf_irc(p, " :%s", parv[parc - 1]);
2892 sendbufto_op_mask(SNO_HACK4);
2896 #if 1 /* FIXME: This should be removed after all HUBs upgraded to ircu2.10.05 */
2898 if (MyConnect(sptr))
2900 return exit_client_msg(cptr, cptr, &me,
2901 "HACK: BURST message outside net.burst from %s", sptr->name);
2905 /* Find the channel, or create it - note that the creation time
2906 * will be 0 if it has to be created */
2907 chptr = get_channel(sptr, parv[1], CREATE);
2908 current_mode = &chptr->mode;
2909 prev_mode = chptr->mode.mode;
2910 if (*chptr->mode.key)
2912 prev_mode |= MODE_KEY;
2913 strcpy(prev_key, chptr->mode.key);
2915 if (chptr->mode.limit)
2916 prev_mode |= MODE_LIMIT;
2918 timestamp = atoi(parv[2]);
2920 /* Copy the new TS when the received creationtime appears to be older */
2921 if (!chptr->creationtime || chptr->creationtime > timestamp)
2923 /* Set the new timestamp */
2924 chptr->creationtime = timestamp;
2925 send_it = 1; /* Make sure we pass on the different timestamp ! */
2926 /* Mark all bans as needed to be wiped out */
2927 for (lp = chptr->banlist; lp; lp = lp->next)
2928 lp->flags |= CHFL_BURST_BAN_WIPEOUT;
2930 * Only the first BURST for this channel can have creationtime > timestamp,
2931 * so at this moment ALL members are on OUR side, and thus all net.riders:
2935 for (lp = chptr->members; lp; lp = lp->next)
2936 lp->flags &= ~CHFL_BURST_JOINED; /* Set later for nicks in the BURST msg */
2937 /* If `wipeout' is set then these will be deopped later. */
2939 /* If the entering creationtime is younger, ignore the modes */
2940 if (chptr->creationtime < timestamp)
2941 netride = 1; /* Only pass on the nicks (so they JOIN) */
2943 /* Prepare buffers to pass the message */
2944 *bparambuf = *bmodebuf = *parabuf = '\0';
2949 prefix_len = sblen = sprintf_irc(sendbuf, "%s BURST %s " TIME_T_FMT,
2950 NumServ(sptr), chptr->chname, chptr->creationtime) - sendbuf;
2952 /* Run over all remaining parameters */
2953 for (n = 3; n < parc; n++)
2954 switch (*parv[n]) /* What type is it ? mode, nicks or bans ? */
2956 case '+': /* modes */
2959 while (*(++p)) /* Run over all mode characters */
2961 switch (*p) /* which mode ? */
2964 * The following cases all do the following:
2965 * - In case wipeout needed, reset 'prev_mode' to indicate this
2966 * mode should not be cancelled.
2967 * - If wipeout or (not netride and the new mode is a change),
2968 * add it to bmodebuf and bparabuf for propagation.
2970 * - Add it to modebuf and parabuf for propagation to the
2971 * clients when not netride and the new mode is a change.
2973 * - If a +s is received, cancel a +p and sent a -p to the
2974 * clients too (if +p was set).
2975 * - If a +p is received and +s is set, ignore the +p.
2980 prev_mode &= ~MODE_INVITEONLY;
2981 if (!(tmp = netride ||
2982 (current_mode->mode & MODE_INVITEONLY)) || wipeout)
2984 bmodebuf[mblen++] = 'i';
2985 current_mode->mode |= MODE_INVITEONLY;
2988 modebuf[mblen2++] = 'i';
2994 char *param = parv[++n];
2995 prev_mode &= ~MODE_KEY;
2996 if (!(tmp = netride || (*current_mode->key &&
2997 (!strcmp(current_mode->key, param) ||
2998 (!wipeout && strcmp(current_mode->key, param) < 0)))) ||
3001 bmodebuf[mblen++] = 'k';
3002 strcat(bparambuf, " ");
3003 strcat(bparambuf, param);
3004 strncpy(current_mode->key, param, KEYLEN);
3006 if (!tmp && !wipeout)
3008 modebuf[mblen2++] = 'k';
3009 parabuf[pblen2++] = ' ';
3010 strcpy(parabuf + pblen2, param);
3011 pblen2 += strlen(param);
3019 unsigned int param = atoi(parv[++n]);
3020 prev_mode &= ~MODE_LIMIT;
3021 if (!(tmp = netride || (current_mode->limit &&
3022 (current_mode->limit == param ||
3023 (!wipeout && current_mode->limit < param)))) || wipeout)
3025 bmodebuf[mblen++] = 'l';
3026 sprintf_irc(bparambuf + strlen(bparambuf), " %d", param);
3027 current_mode->limit = param;
3031 modebuf[mblen2++] = 'l';
3032 pblen2 = sprintf_irc(parabuf + pblen2, " %d", param) - parabuf;
3040 prev_mode &= ~MODE_MODERATED;
3041 if (!(tmp = netride ||
3042 (current_mode->mode & MODE_MODERATED)) || wipeout)
3044 bmodebuf[mblen++] = 'm';
3045 current_mode->mode |= MODE_MODERATED;
3048 modebuf[mblen2++] = 'm';
3054 prev_mode &= ~MODE_NOPRIVMSGS;
3055 if (!(tmp = netride ||
3056 (current_mode->mode & MODE_NOPRIVMSGS)) || wipeout)
3058 bmodebuf[mblen++] = 'n';
3059 current_mode->mode |= MODE_NOPRIVMSGS;
3062 modebuf[mblen2++] = 'n';
3070 if (!netride && !wipeout && (current_mode->mode & MODE_SECRET))
3073 prev_mode &= ~MODE_PRIVATE;
3074 if (!(tmp = netride ||
3075 (current_mode->mode & MODE_PRIVATE)) || wipeout)
3077 bmodebuf[mblen++] = 'p';
3078 current_mode->mode |= MODE_PRIVATE;
3081 modebuf[mblen2++] = 'p';
3087 prev_mode &= ~MODE_SECRET;
3088 if (!(tmp = netride ||
3089 (current_mode->mode & MODE_SECRET)) || wipeout)
3091 bmodebuf[mblen++] = 's';
3092 current_mode->mode |= MODE_SECRET;
3095 modebuf[mblen2++] = 's';
3098 if (!netride && !wipeout && (current_mode->mode & MODE_PRIVATE))
3101 for (i = mblen2 - 1; i >= 0; --i)
3102 modebuf[i + 2] = modebuf[i];
3106 current_mode->mode &= ~MODE_PRIVATE;
3114 prev_mode &= ~MODE_TOPICLIMIT;
3115 if (!(tmp = netride ||
3116 (current_mode->mode & MODE_TOPICLIMIT)) || wipeout)
3118 bmodebuf[mblen++] = 't';
3119 current_mode->mode |= MODE_TOPICLIMIT;
3122 modebuf[mblen2++] = 't';
3126 } /* <-- while over all modes */
3128 bmodebuf[mblen] = '\0';
3129 sendbuf[sblen] = '\0';
3130 if (mblen) /* Anything to send at all ? */
3133 strcpy(sendbuf + sblen, " +");
3135 strcpy(sendbuf + sblen, bmodebuf);
3137 strcpy(sendbuf + sblen, bparambuf);
3138 sblen += strlen(bparambuf);
3140 break; /* Done mode part */
3142 case '%': /* bans */
3144 char *pv, *p = NULL, *ban;
3147 break; /* Ignore bans */
3148 /* Run over all bans */
3149 for (pv = parv[n] + 1; (ban = strtoken(&p, pv, " ")); pv = NULL)
3153 * The following part should do the following:
3154 * - If the new (un)ban is not a _change_ it is ignored.
3155 * - Else, add it to sendbuf for later use.
3156 * - If sendbuf is full, send it, and prepare a new
3157 * message in sendbuf.
3159 ret = add_banid(sptr, chptr, ban, 1, add_banid_not_called);
3162 add_banid_not_called = 0;
3163 /* Mark this new ban so we can send it to the clients later */
3164 chptr->banlist->flags |= CHFL_BURST_BAN;
3167 /* A new ban was added or an existing one needs to be passed on.
3168 * Also add it to sendbuf: */
3169 add_token_to_sendbuf(ban, &sblen, &first, &send_it, '%', 0);
3171 break; /* Done bans part */
3173 default: /* nicks */
3175 char *pv, *p = NULL, *nick, *ptr;
3178 int default_mode = CHFL_DEOPPED;
3179 /* Run over all nicks */
3180 for (pv = parv[n]; (nick = strtoken(&p, pv, ",")); pv = NULL)
3183 if ((ptr = strchr(nick, ':'))) /* New default mode ? */
3185 *ptr = '\0'; /* Fix 'nick' */
3186 acptr = findNUser(nick);
3189 /* Calculate new mode change: */
3190 default_mode = CHFL_DEOPPED;
3194 default_mode |= CHFL_CHANOP;
3195 default_mode &= ~CHFL_DEOPPED;
3197 else if (*ptr == 'v')
3198 default_mode |= CHFL_VOICE;
3204 acptr = findNUser(nick);
3206 * Note that at this point we already received a 'NICK' for any
3207 * <nick> numeric that is joining (and possibly opped) here.
3208 * Therefore we consider the following situations:
3209 * - The <nick> numeric exists and is from the direction of cptr: ok
3210 * - The <nick> numeric does not exist:
3211 * Apparently this previous <nick> numeric was killed (upstream)
3212 * or it collided with an existing <nick> name.
3213 * - The <nick> numeric exists but is from another direction:
3214 * Apparently this previous <nick> numeric was killed,
3215 * and due to a reroute it signed on via another link (probably
3216 * a nick [numeric] collision).
3217 * Note that it can't be a QUIT or SQUIT, because a QUIT would
3218 * come from the same direction as the BURST (cptr) while an
3219 * upstream SQUIT removes the source (server) and we would thus
3220 * have this BURST ignored already.
3221 * This means that if we find the nick and it is from the correct
3222 * direction, it joins. If it doesn't exist or is from another
3223 * direction, we have to ignore it. If all nicks are ignored, we
3224 * remove the channel again when it is empty and don't propagate
3225 * the BURST message.
3227 if (acptr && acptr->from == cptr)
3230 * The following should do the following:
3231 * - Add it to sendbuf for later use.
3232 * - If sendbuf is full, send it, and prepare a new
3233 * message in sendbuf.
3235 add_token_to_sendbuf(nick, &sblen, &first, &send_it, 0,
3237 /* Let is take effect: (Note that in the case of a netride
3238 * 'default_mode' is always CHFL_DEOPPED here). */
3239 add_user_to_channel(chptr, acptr, default_mode);
3240 chptr->members->flags |= CHFL_BURST_JOINED;
3242 } /* <-- Next nick */
3243 if (!chptr->members) /* All nicks collided and channel is empty ? */
3245 sub1_from_channel(chptr);
3246 return 0; /* Forget about the (rest of the) message... */
3248 break; /* Done nicks part */
3250 } /* <-- Next parameter if any */
3251 if (!chptr->members) /* This message only contained bans (then the previous
3252 message only contained collided nicks, see above) */
3254 sub1_from_channel(chptr);
3255 if (!add_banid_not_called)
3256 while (next_removed_overlapped_ban());
3257 return 0; /* Forget about the (rest of the) message... */
3260 /* The last (possibly only) message is always send here */
3261 if (send_it) /* Anything (left) to send ? */
3266 /* send 'sendbuf' to all downlinks */
3267 for (lp = me.serv->down; lp; lp = lp->next)
3269 if (lp->value.cptr == cptr)
3271 if (Protocol(lp->value.cptr) > 9)
3272 sendbufto_one(lp->value.cptr);
3276 * Now we finally can screw sendbuf again...
3277 * Send all changes to the local clients:
3279 * First send all joins and op them, because 2.9 servers
3280 * would protest with a HACK if we first de-opped people.
3281 * However, we don't send the +b bans yes, because we
3282 * DO first want to -b the old bans (otherwise it's confusing).
3285 /* Send all joins: */
3286 for (member = chptr->members; member; member = member->next)
3287 if (member->flags & CHFL_BURST_JOINED)
3289 sendto_channel_butserv(chptr, member->value.cptr, ":%s JOIN :%s",
3290 member->value.cptr->name, chptr->chname);
3291 #ifndef NO_PROTOCOL9
3292 /* And to 2.9 servers: */
3293 sendto_lowprot_butone(cptr, 9, ":%s JOIN %s",
3294 member->value.cptr->name, chptr->chname);
3300 /* Send all +o and +v modes: */
3301 for (member = chptr->members; member; member = member->next)
3303 if ((member->flags & CHFL_BURST_JOINED))
3305 int mode = CHFL_CHANOP;
3308 if ((member->flags & mode))
3310 modebuf[mblen2++] = (mode == CHFL_CHANOP) ? 'o' : 'v';
3311 parabuf[pblen2++] = ' ';
3312 strcpy(parabuf + pblen2, member->value.cptr->name);
3313 pblen2 += strlen(member->value.cptr->name);
3316 modebuf[mblen2] = 0;
3317 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3318 parv[0], chptr->chname, modebuf, parabuf);
3319 #ifndef NO_PROTOCOL9
3320 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3321 parv[0], chptr->chname, modebuf, parabuf,
3322 chptr->creationtime);
3331 if (mode == CHFL_CHANOP)
3339 if (cnt > 0 || mblen2 > 1)
3341 modebuf[mblen2] = 0;
3342 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3343 parv[0], chptr->chname, modebuf, parabuf);
3344 #ifndef NO_PROTOCOL9
3345 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3346 parv[0], chptr->chname, modebuf, parabuf, chptr->creationtime);
3350 #ifndef NO_PROTOCOL9
3351 else if (send_it && !ts_sent)
3353 sendto_lowprot_butone(cptr, 9, ":%s MODE %s + " TIME_T_FMT,
3354 parv[0], chptr->chname, chptr->creationtime);
3369 /* Now cancel all previous simple modes */
3370 if ((prev_mode & MODE_SECRET))
3371 cancel_mode(sptr, chptr, 's', NULL, &count);
3372 if ((prev_mode & MODE_PRIVATE))
3373 cancel_mode(sptr, chptr, 'p', NULL, &count);
3374 if ((prev_mode & MODE_MODERATED))
3375 cancel_mode(sptr, chptr, 'm', NULL, &count);
3376 if ((prev_mode & MODE_TOPICLIMIT))
3377 cancel_mode(sptr, chptr, 't', NULL, &count);
3378 if ((prev_mode & MODE_INVITEONLY))
3379 cancel_mode(sptr, chptr, 'i', NULL, &count);
3380 if ((prev_mode & MODE_NOPRIVMSGS))
3381 cancel_mode(sptr, chptr, 'n', NULL, &count);
3382 if ((prev_mode & MODE_LIMIT))
3384 current_mode->limit = 0;
3385 cancel_mode(sptr, chptr, 'l', NULL, &count);
3387 if ((prev_mode & MODE_KEY))
3389 *current_mode->key = 0;
3390 cancel_mode(sptr, chptr, 'k', prev_key, &count);
3392 current_mode->mode &= ~prev_mode;
3394 /* And deop and devoice all net.riders on my side */
3399 for (lp = chptr->members; lp; lp = lp->next)
3401 if ((lp->flags & CHFL_BURST_JOINED))
3402 continue; /* This is not a net.rider from
3403 this side of the net.junction */
3404 if ((lp->flags & mode))
3407 if (mode == CHFL_CHANOP)
3408 lp->flags |= CHFL_DEOPPED;
3409 cancel_mode(sptr, chptr, m, lp->value.cptr->name, &count);
3412 if (mode == CHFL_VOICE)
3418 /* And finally wipeout all bans that are left */
3419 for (ban = &chptr->banlist; *ban;)
3422 if ((tmp->flags & CHFL_BURST_BAN_WIPEOUT))
3424 cancel_mode(sptr, chptr, 'b', tmp->value.ban.banstr, &count);
3425 /* Copied from del_banid(): */
3427 RunFree(tmp->value.ban.banstr);
3428 RunFree(tmp->value.ban.who);
3430 /* Erase ban-valid-bit, for channel members that are banned */
3431 for (tmp = chptr->members; tmp; tmp = tmp->next)
3432 if ((tmp->flags & (CHFL_BANNED | CHFL_BANVALID)) ==
3433 (CHFL_BANNED | CHFL_BANVALID))
3434 tmp->flags &= ~CHFL_BANVALID; /* `tmp' == channel member */
3439 /* Also wipeout overlapped bans */
3440 if (!add_banid_not_called)
3443 while ((ban = next_removed_overlapped_ban()))
3444 cancel_mode(sptr, chptr, 'b', ban->value.ban.banstr, &count);
3446 cancel_mode(sptr, chptr, 0, NULL, &count); /* flush */
3449 if (send_it && !netride)
3454 if (add_banid_not_called || !(bl = next_removed_overlapped_ban()))
3457 bl = chptr->banlist;
3473 nblen = strlen(bl->value.ban.banstr);
3474 if (cnt == 6 || (!bl && cnt) || pblen2 + nblen + 12 > MODEBUFLEN) /* The last check is to make sure
3475 that the receiving 2.9 will
3476 still process this */
3478 /* Time to send buffer */
3479 modebuf[mblen2] = 0;
3480 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3481 parv[0], chptr->chname, modebuf, parabuf);
3482 #ifndef NO_PROTOCOL9
3483 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s",
3484 parv[0], chptr->chname, modebuf, parabuf);
3486 *modebuf = deban ? '-' : '+';
3491 if (!bl) /* Done ? */
3493 if (deban || (bl->flags & CHFL_BURST_BAN))
3495 /* Add ban to buffers and remove it */
3496 modebuf[mblen2++] = 'b';
3497 parabuf[pblen2++] = ' ';
3498 strcpy(parabuf + pblen2, bl->value.ban.banstr);
3501 bl->flags &= ~CHFL_BURST_BAN;
3505 if (!(bl = next_removed_overlapped_ban()))
3508 modebuf[mblen2++] = '+';
3509 bl = chptr->banlist;
3515 /* Flush MODE [-b]+b ...: */
3516 if (cnt > 0 || mblen2 > 1)
3518 modebuf[mblen2] = 0;
3519 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3520 parv[0], chptr->chname, modebuf, parabuf);
3521 #ifndef NO_PROTOCOL9
3522 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3523 parv[0], chptr->chname, modebuf, parabuf, chptr->creationtime);
3526 #ifndef NO_PROTOCOL9
3527 else if (send_it && !ts_sent)
3528 sendto_lowprot_butone(cptr, 9, ":%s MODE %s + " TIME_T_FMT,
3529 parv[0], chptr->chname, chptr->creationtime);
3539 * parv[0] = sender prefix
3541 * parv[parc - 1] = comment
3543 int m_part(aClient *cptr, aClient *sptr, int parc, char *parv[])
3545 Reg1 aChannel *chptr;
3547 char *p = NULL, *name, pbuf[BUFSIZE];
3548 char *comment = (parc > 2 && !BadPtr(parv[parc - 1])) ? parv[parc - 1] : NULL;
3550 *pbuf = '\0'; /* Initialize the part buffer... -Kev */
3552 sptr->flags &= ~FLAGS_TS8;
3554 if (parc < 2 || parv[1][0] == '\0')
3556 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "PART");
3560 for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
3562 chptr = get_channel(sptr, name, !CREATE);
3565 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
3568 if (*name == '&' && !MyUser(sptr))
3570 /* Do not use IsMember here: zombies must be able to part too */
3571 if (!(lp = find_user_link(chptr->members, sptr)))
3573 /* Normal to get when our client did a kick
3574 for a remote client (who sends back a PART),
3575 so check for remote client or not --Run */
3577 sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
3581 /* Recreate the /part list for sending to servers */
3588 if (can_send(sptr, chptr) != 0) /* Returns 0 if we CAN send */
3590 /* Send part to all clients */
3591 if (!(lp->flags & CHFL_ZOMBIE))
3594 sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], chptr->chname,
3597 sendto_channel_butserv(chptr, sptr, PartFmt1, parv[0], chptr->chname);
3599 else if (MyUser(sptr))
3602 sendto_one(sptr, PartFmt2, parv[0], chptr->chname, comment);
3604 sendto_one(sptr, PartFmt1, parv[0], chptr->chname);
3606 remove_user_from_channel(sptr, chptr);
3608 /* Send out the parts to all servers... -Kev */
3612 sendto_serv_butone(cptr, PartFmt2, parv[0], pbuf, comment);
3614 sendto_serv_butone(cptr, PartFmt1, parv[0], pbuf);
3622 * parv[0] = sender prefix
3624 * parv[2] = client to kick
3625 * parv[parc-1] = kick comment
3627 int m_kick(aClient *cptr, aClient *sptr, int parc, char *parv[])
3634 sptr->flags &= ~FLAGS_TS8;
3636 if (parc < 3 || *parv[1] == '\0')
3638 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KICK");
3643 send_hack_notice(cptr, sptr, parc, parv, 1, 3);
3645 comment = (BadPtr(parv[parc - 1])) ? parv[0] : parv[parc - 1];
3646 if (strlen(comment) > (size_t)TOPICLEN)
3647 comment[TOPICLEN] = '\0';
3649 *nickbuf = *buf = '\0';
3651 chptr = get_channel(sptr, parv[1], !CREATE);
3654 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
3657 if (IsLocalChannel(parv[1]) && !MyUser(sptr))
3659 if (IsModelessChannel(parv[1]))
3661 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
3665 if (!IsServer(cptr) && !is_chan_op(sptr, chptr))
3667 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3668 me.name, parv[0], chptr->chname);
3672 lp2 = find_user_link(chptr->members, sptr);
3673 if (MyUser(sptr) || Protocol(cptr) < 10)
3675 if (!(who = find_chasing(sptr, parv[2], NULL)))
3676 return 0; /* No such user left! */
3678 else if (!(who = findNUser(parv[2])))
3679 return 0; /* No such user left! */
3680 /* if the user is +k, prevent a kick from local user */
3681 if (IsChannelService(who) && MyUser(sptr))
3683 sendto_one(sptr, err_str(ERR_ISCHANSERVICE), me.name,
3684 parv[0], who->name, chptr->chname);
3687 #ifdef NO_OPER_DEOP_LCHAN
3689 * Prevent kicking opers from local channels -DM-
3691 if (IsOperOnLocalChannel(who, chptr->chname))
3693 sendto_one(sptr, err_str(ERR_ISOPERLCHAN), me.name,
3694 parv[0], who->name, chptr->chname);
3699 if (((lp = find_user_link(chptr->members, who)) &&
3700 !(lp->flags & CHFL_ZOMBIE)) || IsServer(sptr))
3702 if (who->from != cptr &&
3703 ((lp2 && (lp2->flags & CHFL_DEOPPED)) || (!lp2 && IsUser(sptr))))
3707 * cptr must be a server (or cptr == sptr and
3708 * sptr->flags can't have DEOPPED set
3709 * when CHANOP is set).
3711 sendto_one(cptr, ":%s JOIN %s", who->name, parv[1]);
3712 if (lp->flags & CHFL_CHANOP)
3714 if (Protocol(cptr) < 10)
3715 sendto_one(cptr, ":%s MODE %s +o %s " TIME_T_FMT,
3716 me.name, parv[1], who->name, chptr->creationtime);
3718 sendto_one(cptr, "%s MODE %s +o %s%s " TIME_T_FMT,
3719 NumServ(&me), parv[1], NumNick(who), chptr->creationtime);
3721 if (lp->flags & CHFL_VOICE)
3723 if (Protocol(cptr) < 10)
3724 sendto_one(cptr, ":%s MODE %s +v %s " TIME_T_FMT,
3725 me.name, chptr->chname, who->name, chptr->creationtime);
3727 sendto_one(cptr, "%s MODE %s +v %s%s " TIME_T_FMT,
3728 NumServ(&me), parv[1], NumNick(who), chptr->creationtime);
3734 sendto_channel_butserv(chptr, sptr,
3735 ":%s KICK %s %s :%s", parv[0], chptr->chname, who->name, comment);
3736 if (!IsLocalChannel(parv[1]))
3738 sendto_lowprot_butone(cptr, 9, ":%s KICK %s %s :%s",
3739 parv[0], chptr->chname, who->name, comment);
3740 sendto_highprot_butone(cptr, 10, ":%s KICK %s %s%s :%s",
3741 parv[0], parv[1], NumNick(who), comment);
3752 * X --a--> A --b--> B --d--> D
3756 * Where `who' is being KICK-ed by a "KICK" message received by server 'A'
3757 * via 'a', or on server 'B' via either 'b' or 'c', or on server D via 'd'.
3759 * a) On server A : set CHFL_ZOMBIE for `who' (lp) and pass on the KICK.
3760 * Remove the user immedeately when no users are left on the channel.
3761 * b) On server B : remove the user (who/lp) from the channel, send a
3762 * PART upstream (to A) and pass on the KICK.
3763 * c) KICKed by `client'; On server B : remove the user (who/lp) from the
3764 * channel, and pass on the KICK.
3765 * d) On server D : remove the user (who/lp) from the channel, and pass on
3769 * - Setting the ZOMBIE flag never hurts, we either remove the
3770 * client after that or we don't.
3771 * - The KICK message was already passed on, as should be in all cases.
3772 * - `who' is removed in all cases except case a) when users are left.
3773 * - A PART is only sent upstream in case b).
3779 * 1 --- 2 --- 3 --- 4 --- 5
3783 * We also need to turn 'who' into a zombie on servers 1 and 6,
3784 * because a KICK from 'who' (kicking someone else in that direction)
3785 * can arrive there afterwards - which should not be bounced itself.
3786 * Therefore case a) also applies for servers 1 and 6.
3790 /* Default for case a): */
3791 lp->flags |= CHFL_ZOMBIE;
3792 /* Case b) or c) ?: */
3793 if (MyUser(who)) /* server 4 */
3795 if (IsServer(cptr)) /* Case b) ? */
3796 sendto_one(cptr, PartFmt1, who->name, parv[1]);
3797 remove_user_from_channel(who, chptr);
3800 if (who->from == cptr) /* True on servers 1, 5 and 6 */
3802 aClient *acptr = IsServer(sptr) ? sptr : sptr->user->server;
3803 for (; acptr != &me; acptr = acptr->serv->up)
3804 if (acptr == who->user->server) /* Case d) (server 5) */
3806 remove_user_from_channel(who, chptr);
3810 /* Case a) (servers 1, 2, 3 and 6) */
3811 for (lp = chptr->members; lp; lp = lp->next)
3812 if (!(lp->flags & CHFL_ZOMBIE))
3815 remove_user_from_channel(who, chptr);
3818 sendto_op_mask(SNO_HACK2, "%s is now a zombie on %s",
3819 who->name, chptr->chname);
3824 else if (MyUser(sptr))
3825 sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
3826 me.name, parv[0], who->name, chptr->chname);
3834 * parv[0] = sender prefix
3836 * parv[parc - 1] = topic (if parc > 2)
3838 int m_topic(aClient *cptr, aClient *sptr, int parc, char *parv[])
3841 char *topic = NULL, *name, *p = NULL;
3845 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "TOPIC");
3850 topic = parv[parc - 1];
3852 for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
3855 if (!IsChannelName(name) || !(chptr = FindChannel(name)) ||
3856 ((topic || SecretChannel(chptr)) && !IsMember(sptr, chptr)))
3858 sendto_one(sptr, err_str(chptr ? ERR_NOTONCHANNEL : ERR_NOSUCHCHANNEL),
3859 me.name, parv[0], chptr ? chptr->chname : name);
3862 if (IsModelessChannel(name))
3864 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
3868 if (IsLocalChannel(name) && !MyUser(sptr))
3871 if (!topic) /* only asking for topic */
3873 if (chptr->topic[0] == '\0')
3874 sendto_one(sptr, rpl_str(RPL_NOTOPIC), me.name, parv[0], chptr->chname);
3877 sendto_one(sptr, rpl_str(RPL_TOPIC),
3878 me.name, parv[0], chptr->chname, chptr->topic);
3879 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME),
3880 me.name, parv[0], chptr->chname,
3881 chptr->topic_nick, chptr->topic_time);
3884 else if (((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
3885 is_chan_op(sptr, chptr)) && topic)
3887 /* setting a topic */
3888 strncpy(chptr->topic, topic, TOPICLEN);
3889 strncpy(chptr->topic_nick, sptr->name, NICKLEN);
3890 chptr->topic_time = now;
3891 sendto_serv_butone(cptr, ":%s TOPIC %s :%s",
3892 parv[0], chptr->chname, chptr->topic);
3893 sendto_channel_butserv(chptr, sptr, ":%s TOPIC %s :%s",
3894 parv[0], chptr->chname, chptr->topic);
3897 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3898 me.name, parv[0], chptr->chname);
3905 * parv[0] - sender prefix
3906 * parv[1] - user to invite
3907 * parv[2] - channel name
3909 * - INVITE now is accepted only if who does it is chanop (this of course
3910 * implies that channel must exist and he must be on it).
3912 * - On the other side it IS processed even if channel is NOT invite only
3913 * leaving room for other enhancements like inviting banned ppl. -- Nemesi
3916 int m_invite(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
3921 if (parc < 3 || *parv[2] == '\0')
3923 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "INVITE");
3927 if (!(acptr = FindUser(parv[1])))
3929 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
3933 if (is_silenced(sptr, acptr))
3937 clean_channelname(parv[2]);
3938 else if (IsLocalChannel(parv[2]))
3941 if (*parv[2] == '0' || !IsChannelName(parv[2]))
3944 if (!(chptr = FindChannel(parv[2])))
3946 if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2]))
3948 sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], parv[2]);
3952 /* Do not disallow to invite to non-existant #channels, otherwise they
3953 would simply first be created, causing only MORE bandwidth usage. */
3954 if (MyConnect(sptr))
3956 if (check_target_limit(sptr, acptr, acptr->name, 0))
3959 sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
3960 acptr->name, parv[2]);
3962 if (acptr->user->away)
3963 sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
3964 acptr->name, acptr->user->away);
3967 sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
3968 acptr->name, parv[2]);
3973 if (!IsMember(sptr, chptr))
3975 sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
3980 if (IsMember(acptr, chptr))
3982 sendto_one(sptr, err_str(ERR_USERONCHANNEL),
3983 me.name, parv[0], acptr->name, chptr->chname);
3987 if (MyConnect(sptr))
3989 if (!is_chan_op(sptr, chptr))
3991 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3992 me.name, parv[0], chptr->chname);
3996 /* If we get here, it was a VALID and meaningful INVITE */
3998 if (check_target_limit(sptr, acptr, acptr->name, 0))
4001 sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
4002 acptr->name, chptr->chname);
4004 if (acptr->user->away)
4005 sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
4006 acptr->name, acptr->user->away);
4009 if (MyConnect(acptr))
4010 add_invite(acptr, chptr);
4012 sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
4013 acptr->name, chptr->chname);
4018 static int number_of_zombies(aChannel *chptr)
4022 for (lp = chptr->members; lp; lp = lp->next)
4023 if (lp->flags & CHFL_ZOMBIE)
4031 * parv[0] = sender prefix
4032 * parv[1] = channel list or user/time limit
4033 * parv[2...] = more user/time limits
4035 int m_list(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
4038 char *name, *p = NULL;
4039 int show_usage = 0, show_channels = 0, param;
4040 aListingArgs args = {
4041 2147483647, /* max_time */
4043 4294967295U, /* max_users */
4045 0, /* topic_limits */
4046 2147483647, /* max_topic_time */
4047 0, /* min_topic_time */
4051 if (sptr->listing) /* Already listing ? */
4053 sptr->listing->chptr->mode.mode &= ~MODE_LISTED;
4054 RunFree(sptr->listing);
4055 sptr->listing = NULL;
4056 sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, sptr->name);
4058 return 0; /* Let LIST abort a listing. */
4061 if (parc < 2) /* No arguments given to /LIST ? */
4063 #ifdef DEFAULT_LIST_PARAM
4064 static char *defparv[MAXPARA + 1];
4065 static int defparc = 0;
4066 static char lp[] = DEFAULT_LIST_PARAM;
4074 defparv[defparc++] = t = strtok(s, " ");
4075 while (t && defparc < MAXPARA)
4077 if ((t = strtok(NULL, " ")))
4078 defparv[defparc++] = t;
4081 for (i = 1; i < defparc; i++)
4082 parv[i] = defparv[i];
4085 #endif /* DEFAULT_LIST_PARAM */
4088 /* Decode command */
4089 for (param = 1; !show_usage && parv[param]; param++)
4091 char *p = parv[param];
4100 args.topic_limits = 1;
4106 if (*p != '<' && *p != '>')
4122 time_t val = atoi(p);
4125 if (val < 80000000) /* Toggle UTC/offset */
4129 * 'TStime() - chptr->creationtime < val * 60'
4131 * 'chptr->creationtime > TStime() - val * 60'
4134 args.min_time = TStime() - val * 60;
4136 args.min_topic_time = TStime() - val * 60;
4138 else if (is_time == 1) /* Creation time in UTC was entered */
4139 args.max_time = val;
4140 else /* Topic time in UTC was entered */
4141 args.max_topic_time = val;
4143 else if (val < 80000000)
4146 args.max_time = TStime() - val * 60;
4148 args.max_topic_time = TStime() - val * 60;
4150 else if (is_time == 1)
4151 args.min_time = val;
4153 args.min_topic_time = val;
4155 else if (p[-1] == '<')
4156 args.max_users = atoi(p);
4158 args.min_users = atoi(p);
4159 if ((p = strchr(p, ',')))
4165 if (!IsChannelName(p))
4170 if (parc != 2) /* Don't allow a mixture of channels with <,> */
4177 while (!show_usage && p); /* p points after comma, or is NULL */
4182 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4183 "Usage: \002/QUOTE LIST\002 \037parameters\037");
4184 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4185 "Where \037parameters\037 is a space or comma seperated "
4186 "list of one or more of:");
4187 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4188 " \002<\002\037max_users\037 ; Show all channels with less "
4189 "than \037max_users\037.");
4190 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4191 " \002>\002\037min_users\037 ; Show all channels with more "
4192 "than \037min_users\037.");
4193 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4194 " \002C<\002\037max_minutes\037 ; Channels that exist less "
4195 "than \037max_minutes\037.");
4196 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4197 " \002C>\002\037min_minutes\037 ; Channels that exist more "
4198 "than \037min_minutes\037.");
4199 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4200 " \002T<\002\037max_minutes\037 ; Channels with a topic last "
4201 "set less than \037max_minutes\037 ago.");
4202 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4203 " \002T>\002\037min_minutes\037 ; Channels with a topic last "
4204 "set more than \037min_minutes\037 ago.");
4205 sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4206 "Example: LIST <3,>1,C<10,T>0 ; 2 users, younger than 10 min., "
4211 sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, parv[0]);
4215 if (args.max_users > args.min_users + 1 && args.max_time > args.min_time &&
4216 args.max_topic_time > args.min_topic_time) /* Sanity check */
4218 if ((sptr->listing = (aListingArgs *)RunMalloc(sizeof(aListingArgs))))
4220 memcpy(sptr->listing, &args, sizeof(aListingArgs));
4221 if ((sptr->listing->chptr = channel))
4223 int m = channel->mode.mode & MODE_LISTED;
4224 list_next_channels(sptr, 64);
4225 channel->mode.mode |= m;
4228 RunFree(sptr->listing);
4229 sptr->listing = NULL;
4232 sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
4236 for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
4238 chptr = FindChannel(name);
4239 if (chptr && ShowChannel(sptr, chptr) && sptr->user)
4240 sendto_one(sptr, rpl_str(RPL_LIST), me.name, parv[0],
4241 ShowChannel(sptr, chptr) ? chptr->chname : "*",
4242 chptr->users - number_of_zombies(chptr), chptr->topic);
4245 sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
4250 * m_names - Added by Jto 27 Apr 1989
4252 * parv[0] = sender prefix
4255 int m_names(aClient *cptr, aClient *sptr, int parc, char *parv[])
4257 Reg1 aChannel *chptr;
4258 Reg2 aClient *c2ptr;
4260 aChannel *ch2ptr = NULL;
4261 int idx, flag, len, mlen;
4262 char *s, *para = parc > 1 ? parv[1] : NULL;
4264 if (parc > 2 && hunt_server(1, cptr, sptr, ":%s NAMES %s %s", 2, parc, parv))
4267 mlen = strlen(me.name) + 10 + strlen(sptr->name);
4271 s = strchr(para, ',');
4275 m_names(cptr, sptr, parc, parv);
4277 clean_channelname(para);
4278 ch2ptr = FindChannel(para);
4282 * First, do all visible channels (public and the one user self is)
4285 for (chptr = channel; chptr; chptr = chptr->nextch)
4287 if ((chptr != ch2ptr) && !BadPtr(para))
4288 continue; /* -- wanted a specific channel */
4289 if (!MyConnect(sptr) && BadPtr(para))
4292 if (!ShowChannel(sptr, chptr))
4293 continue; /* -- users on this are not listed */
4296 /* Find users on same channel (defined by chptr) */
4299 len = strlen(chptr->chname);
4300 strcpy(buf + 2, chptr->chname);
4301 strcpy(buf + 2 + len, " :");
4303 if (PubChannel(chptr))
4305 else if (SecretChannel(chptr))
4309 for (lp = chptr->members; lp; lp = lp->next)
4311 c2ptr = lp->value.cptr;
4313 if (sptr != c2ptr && IsInvisible(c2ptr) && !IsMember(sptr, chptr))
4316 if (lp->flags & CHFL_ZOMBIE)
4318 if (lp->value.cptr != sptr)
4326 else if (lp->flags & CHFL_CHANOP)
4331 else if (lp->flags & CHFL_VOICE)
4336 strcat(buf, c2ptr->name);
4338 idx += strlen(c2ptr->name) + 1;
4343 sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
4344 if (c2ptr != findNUser(yxx))
4346 sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
4349 if (mlen + idx + NICKLEN + 11 > BUFSIZE)
4351 if (mlen + idx + NICKLEN + 5 > BUFSIZE)
4353 /* space, modifier, nick, \r \n \0 */
4355 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4357 strncpy(buf + 2, chptr->chname, len + 1);
4360 if (PubChannel(chptr))
4362 else if (SecretChannel(chptr))
4369 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4373 sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
4374 ch2ptr ? ch2ptr->chname : para);
4378 /* Second, do all non-public, non-secret channels in one big sweep */
4380 strcpy(buf, "* * :");
4383 for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
4386 int showflag = 0, secret = 0;
4389 if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
4394 lp = c2ptr->user->channel;
4396 * Don't show a client if they are on a secret channel or when
4397 * they are on a channel sptr is on since they have already
4398 * been show earlier. -avalon
4402 ch3ptr = lp->value.chptr;
4404 if (PubChannel(ch3ptr) || IsMember(sptr, ch3ptr))
4407 if (SecretChannel(ch3ptr))
4411 if (showflag) /* Have we already shown them ? */
4414 if (secret) /* On any secret channels ? */
4417 strcat(buf, c2ptr->name);
4419 idx += strlen(c2ptr->name) + 1;
4424 sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
4425 if (c2ptr != findNUser(yxx))
4427 sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
4432 if (mlen + idx + NICKLEN + 9 > BUFSIZE)
4434 if (mlen + idx + NICKLEN + 3 > BUFSIZE) /* space, \r\n\0 */
4437 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4438 strcpy(buf, "* * :");
4444 sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4445 sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
4449 void send_user_joins(aClient *cptr, aClient *user)
4452 Reg2 aChannel *chptr;
4453 Reg3 int cnt = 0, len = 0, clen;
4457 strcpy(buf + 1, user->name);
4458 strcat(buf, " JOIN ");
4459 len = strlen(user->name) + 7;
4461 for (lp = user->user->channel; lp; lp = lp->next)
4463 chptr = lp->value.chptr;
4464 if ((mask = strchr(chptr->chname, ':')))
4465 if (match(++mask, cptr->name))
4467 if (*chptr->chname == '&')
4469 if (is_zombie(user, chptr))
4471 clen = strlen(chptr->chname);
4472 if (clen + 1 + len > BUFSIZE - 3)
4476 buf[len - 1] = '\0';
4477 sendto_one(cptr, "%s", buf);
4480 strcpy(buf + 1, user->name);
4481 strcat(buf, " JOIN ");
4482 len = strlen(user->name) + 7;
4485 strcpy(buf + len, chptr->chname);
4495 sendto_one(cptr, "%s", buf);
4501 * send_hack_notice()
4503 * parc & parv[] are the same as that of the calling function:
4504 * mtype == 1 is from m_mode, 2 is from m_create, 3 is from m_kick.
4506 * This function prepares sendbuf with the server notices and wallops
4507 * to be sent for all hacks. -Ghostwolf 18-May-97
4510 static void send_hack_notice(aClient *cptr, aClient *sptr, int parc,
4511 char *parv[], int badop, int mtype)
4514 static char params[MODEBUFLEN];
4516 chptr = FindChannel(parv[1]);
4519 if (Protocol(cptr) < 10) /* We don't get numeric nicks from P09 */
4520 { /* servers, so this can be sent "As Is" */
4525 strcat(params, " ");
4526 strcat(params, parv[i++]);
4528 sprintf_irc(sendbuf,
4529 ":%s NOTICE * :*** Notice -- %sHACK(%d): %s MODE %s %s%s [" TIME_T_FMT
4530 "]", me.name, (badop == 3) ? "BOUNCE or " : "", badop, parv[0],
4531 parv[1], parv[2], params, chptr->creationtime);
4532 sendbufto_op_mask((badop == 3) ? SNO_HACK3 : (badop ==
4533 4) ? SNO_HACK4 : SNO_HACK2);
4535 if ((IsServer(sptr)) && (badop == 2))
4537 sprintf_irc(sendbuf, ":%s DESYNCH :HACK: %s MODE %s %s%s",
4538 me.name, parv[0], parv[1], parv[2], params);
4539 sendbufto_serv_butone(cptr);
4542 else if (mtype == 3)
4544 sprintf_irc(sendbuf,
4545 ":%s NOTICE * :*** Notice -- HACK: %s KICK %s %s :%s",
4546 me.name, sptr->name, parv[1], parv[2], parv[3]);
4547 sendbufto_op_mask(SNO_HACK4);
4552 /* P10 servers require numeric nick conversion before sending. */
4555 case 1: /* Convert nicks for MODE HACKs here */
4557 char *mode = parv[2];
4560 while (*mode && *mode != 'o' && *mode != 'v')
4562 strcat(params, " ");
4563 if (*mode == 'o' || *mode == 'v')
4565 register aClient *acptr;
4566 if ((acptr = findNUser(parv[i])) != NULL) /* Convert nicks here */
4567 strcat(params, acptr->name);
4570 strcat(params, "<");
4571 strcat(params, parv[i]);
4572 strcat(params, ">");
4575 else /* If it isn't a numnick, send it 'as is' */
4576 strcat(params, parv[i]);
4579 sprintf_irc(sendbuf,
4580 ":%s NOTICE * :*** Notice -- %sHACK(%d): %s MODE %s %s%s ["
4581 TIME_T_FMT "]", me.name, (badop == 3) ? "BOUNCE or " : "", badop,
4582 parv[0], parv[1], parv[2], params, chptr->creationtime);
4583 sendbufto_op_mask((badop == 3) ? SNO_HACK3 : (badop ==
4584 4) ? SNO_HACK4 : SNO_HACK2);
4586 if ((IsServer(sptr)) && (badop == 2))
4588 sprintf_irc(sendbuf, ":%s DESYNCH :HACK: %s MODE %s %s%s",
4589 me.name, parv[0], parv[1], parv[2], params);
4590 sendbufto_serv_butone(cptr);
4594 case 2: /* No conversion is needed for CREATE; the only numnick is sptr */
4596 sendto_serv_butone(cptr, ":%s DESYNCH :HACK: %s CREATE %s %s",
4597 me.name, sptr->name, chptr->chname, parv[2]);
4598 sendto_op_mask(SNO_HACK2, "HACK(2): %s CREATE %s %s",
4599 sptr->name, chptr->chname, parv[2]);
4602 case 3: /* Convert nick in KICK message */
4605 if ((acptr = findNUser(parv[2])) != NULL) /* attempt to convert nick */
4606 sprintf_irc(sendbuf,
4607 ":%s NOTICE * :*** Notice -- HACK: %s KICK %s %s :%s",
4608 me.name, sptr->name, parv[1], acptr->name, parv[3]);
4609 else /* if conversion fails, send it 'as is' in <>'s */
4610 sprintf_irc(sendbuf,
4611 ":%s NOTICE * :*** Notice -- HACK: %s KICK %s <%s> :%s",
4612 me.name, sptr->name, parv[1], parv[2], parv[3]);
4613 sendbufto_op_mask(SNO_HACK4);