Files
bitchx/source/names.c
Kevin Easton 07ab60f3ff Test sent_kick instead of kickcount for NICKFLOOD kicking
kickcount is for counting KICKs sent by the user to detect KICK floods.

The userlist and isme() tests are already done prior to calling handle_nickflood() so they are
not needed here.
2017-06-11 00:33:33 +10:00

2070 lines
47 KiB
C

/*
* names.c: This here is used to maintain a list of all the people currently
* on your channel. Seems to work
*
*
* Written By Michael Sandrof
*
* Copyright(c) 1990
*
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
*/
#include "irc.h"
static char cvsrevision[] = "$Id$";
CVS_REVISION(names_c)
#include "struct.h"
#include "ircaux.h"
#include "names.h"
#include "flood.h"
#include "window.h"
#include "screen.h"
#include "server.h"
#include "lastlog.h"
#include "list.h"
#include "output.h"
#include "userlist.h"
#include "timer.h"
#include "input.h"
#include "hook.h"
#include "parse.h"
#include "whowas.h"
#include "misc.h"
#include "vars.h"
#include "keys.h"
#include "tcl_bx.h"
#include "status.h"
#include "userlist.h"
#include "hash2.h"
#include "cset.h"
#include "gui.h"
#define MAIN_SOURCE
#include "modval.h"
extern AJoinList *ajoin_list;
static void add_to_mode_list (char *, int, char *);
static void check_mode_list_join (char *, int);
static void show_channel (ChannelList *);
static void clear_channel (ChannelList *);
char *BX_recreate_mode (ChannelList *);
static void clear_mode_list (int);
static void apply_channel_modes (char *, char *, ChannelList *);
void BX_clear_bans (ChannelList *);
static char mode_str[] = "aciklmnprstzR";
char new_channel_format[BIG_BUFFER_SIZE];
static struct modelist
{
char *chan;
int server;
char *mode;
struct modelist *next;
} *mode_list = NULL;
static struct joinlist
{
char *chan;
int server,
gotinfo,
winref;
struct timeval tv;
struct joinlist *next;
} *join_list = NULL;
/*
* check_channel_type: checks if the given channel is a normal #channel
* or a new !channel from irc2.10. If the latter, then it reformats it
* a bit into a more user-friendly form.
*/
char * check_channel_type (char *channel)
{
if (*channel != '!' || strlen(channel) < 6)
return channel;
snprintf(new_channel_format, sizeof new_channel_format, "[%.6s] %s", channel, channel + 6);
return new_channel_format;
}
/* clear_channel: erases all entries in a nick list for the given channel */
static void clear_channel(ChannelList *chan)
{
NickList *Nick, *n;
while((Nick = next_nicklist(chan, NULL)))
{
n = find_nicklist_in_channellist(Nick->nick, chan, REMOVE_FROM_LIST);
add_to_whowas_buffer(n, chan->channel, NULL, NULL);
}
clear_nicklist_hashtable(chan);
chan->totalnicks = 0;
}
ChannelList *BX_lookup_channel(const char *channel, int server, int unlink)
{
register ChannelList *chan = NULL,
*last = NULL;
if (server <= -2)
return NULL;
if (server == -1)
{
server = primary_server;
if (server == -1)
return NULL;
}
if (!channel || !*channel || !strcmp(channel, "*"))
channel = get_current_channel_by_refnum(0);
chan = get_server_channels(server);
if (!chan || !channel || !*channel)
return NULL;
while (chan)
{
if (chan->channel && !my_stricmp(chan->channel, channel))
{
if (unlink == CHAN_UNLINK)
{
if (last)
last->next = chan->next;
else
set_server_channels(server, chan->next);
}
break;
}
last = chan;
chan = chan->next;
}
return chan;
}
extern void set_waiting_channel (int i)
{
Window *tmp = NULL;
while ((traverse_all_windows(&tmp)))
if (tmp->server == i && tmp->current_channel)
{
#if 0
if (tmp->bind_channel)
tmp->waiting_channel = tmp->current_channel;
else
new_free(&tmp->current_channel);
tmp->current_channel = NULL;
#else
if (tmp->waiting_channel)
continue;
tmp->waiting_channel = tmp->current_channel;
tmp->current_channel = NULL;
#endif
}
}
/* if the user is on the given channel, it returns 1. */
extern int BX_im_on_channel (char *channel, int server)
{
return (channel?(lookup_channel(channel, server, 0) ? 1 : 0) : 0);
}
void add_userhost_to_channel (char *channel, char *nick, int server, char *userhost)
{
NickList *new;
ChannelList *chan;
if ((chan = lookup_channel(channel, server, 0)) != NULL)
if ((new = find_nicklist_in_channellist(nick, chan, 0)))
malloc_strcpy(&new->host, userhost);
}
/*
* add_channel: adds the named channel to the channel list. If the channel
* is already in the list, then the channel gets cleaned, and ready for use
* again. The added channel becomes the current channel as well.
*/
ChannelList * BX_add_channel(char *channel, int server, int refnum)
{
ChannelList *new = NULL;
WhowasChanList *whowaschan;
if ((new = lookup_channel(channel, server, CHAN_NOUNLINK)) != NULL)
{
new->connected = 1;
new->mode = 0;
new->limit = 0;
new_free(&new->s_mode);
new->server = server;
new->window = current_window;
new->refnum = new->window->refnum;
malloc_strcpy(&(new->channel), channel);
clear_channel(new);
clear_bans(new);
}
else
{
Window *tmp = NULL;
if (!(whowaschan = check_whowas_chan_buffer(channel, refnum, 1)))
{
new = (ChannelList *) new_malloc(sizeof(ChannelList));
new->connected = 1;
get_time(&new->channel_create);
malloc_strcpy(&(new->channel), channel);
add_to_list((List **)&new->csets, (List *)create_csets_for_channel(channel));
}
else
{
new = whowaschan->channellist;
new_free(&whowaschan->channel);
new_free((char **)&whowaschan);
new_free(&(new->key));
new->mode = 0;
new_free(&new->s_mode);
new->limit = new->i_mode = 0;
clear_channel(new);
clear_bans(new);
}
if ((!new->window || !(tmp = get_window_by_refnum(new->window->refnum))) && current_window)
{
new->window = tmp ? tmp : current_window;
new->refnum = new->window->refnum;
}
new->server = server;
new->flags.got_modes = new->flags.got_who = new->flags.got_bans = 1;
get_time(&new->join_time);
add_server_channels(server, new);
}
new->have_op = 0;
new->voice = 0;
new->hop = 0;
if (!is_current_channel(channel, server, 0))
{
Window *tmp = NULL;
while ((traverse_all_windows(&tmp)))
{
if (tmp->server != from_server)
continue;
if (tmp->name && (!strcmp(tmp->name, "oper_view") || !strcmp(tmp->name, "debug")))
continue;
if (!tmp->waiting_channel && !tmp->bind_channel)
continue;
if (tmp->bind_channel && tmp->server == from_server)
{
char *p, *q;
p = LOCAL_COPY(tmp->bind_channel);
while ((q = next_in_comma_list(p, &p)))
{
if (!q || !*q)
break;
if (my_stricmp(q, channel))
continue;
set_current_channel_by_refnum(tmp->refnum, channel);
new->window = tmp;
new->refnum = tmp->refnum;
update_all_windows();
return new;
}
}
if (tmp->waiting_channel && tmp->server == from_server)
{
char *p, *q;
p = LOCAL_COPY(tmp->waiting_channel);
while ((q = next_in_comma_list(p, &p)))
{
if (!q || !*q)
break;
if (my_stricmp(q, channel))
continue;
set_current_channel_by_refnum(tmp->refnum, channel);
new->window = tmp;
new->refnum = tmp->refnum;
new_free(&tmp->waiting_channel);
update_all_windows();
return new;
}
}
}
set_current_channel_by_refnum(new->window?new->window->refnum:0, channel);
}
update_all_windows();
return new;
}
/*
* add_to_channel: adds the given nickname to the given channel. If the
* nickname is already on the channel, nothing happens. If the channel is
* not on the channel list, nothing happens (although perhaps the channel
* should be addded to the list? but this should never happen)
*/
ChannelList *BX_add_to_channel(char *channel, char *nick, int server, int oper, int voice, char *userhost, char *server1, char *away, int serv_split, int server_hops)
{
NickList *new = NULL;
ChannelList *chan = NULL;
WhowasList *whowas;
int ischop = oper;
if (!(*channel == '*'))
{
if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)))
{
if (*nick == '+')
{
nick++;
if (!my_stricmp(nick, get_server_nickname(server)))
{
check_mode_list_join(channel, server);
chan->voice = 1;
}
}
if (ischop && ischop != -1)
{
if (!my_stricmp(nick, get_server_nickname(server)))
{
check_mode_list_join(channel, server);
chan->have_op = 1;
}
}
if (!(new = find_nicklist_in_channellist(nick, chan, 0)))
{
if (!(whowas = check_whowas_buffer(nick, userhost, channel)))
{
new = (NickList *) new_malloc(sizeof(NickList));
new->idle_time = new->kicktime =
new->doptime = new->nicktime =
new->floodtime = new->bantime = now;
new->joincount = 1;
malloc_strcpy(&(new->nick), nick);
#ifdef WANT_USERLIST
new->userlist = lookup_userlevelc("*", userhost, channel, NULL);
new->shitlist = nickinshit(nick, userhost);
#endif
new->serverhops = server_hops;
}
else
{
new = whowas->nicklist;
new_free(&whowas->channel);
new_free(&whowas->server1);
new_free(&whowas->server2);
new_free((char **)&whowas);
malloc_strcpy(&(new->nick), nick);
new->idle_time = new->kicktime =
new->doptime = new->nicktime =
new->floodtime = new->bantime = now;
new->sent_reop = new->sent_deop =
new->bancount = new->nickcount =
new->dopcount = new->kickcount =
new->floodcount = new->ip_count =
new->sent_voice = new->sent_kick = 0;
new->flags = 0;
new->serverhops = server_hops;
new->next = NULL;
}
if (server1)
malloc_strcpy(&new->server, server1);
add_nicklist_to_channellist(new, chan);
update_stats(JOINLIST, new, chan, serv_split);
}
malloc_strcpy(&new->host, userhost);
if (ischop > 0)
new->flags |= NICK_CHANOP;
if (voice > 0)
new->flags |= NICK_VOICE;
if (away)
{
if (strchr(away,'H'))
new->flags &= ~NICK_AWAY;
else
new->flags |= NICK_AWAY;
if (strchr(away, '*'))
new->flags |= NICK_IRCOP;
if (strchr(away, '%'))
new->flags |= NICK_HALFOP;
}
}
else if (check_whowas_chan_buffer(channel, -1, 0))
{
if (*nick == '+') nick++;
new = (NickList *) new_malloc(sizeof(NickList));
new->idle_time = new->kicktime =
new->doptime = new->nicktime =
new->floodtime = new->bantime = now;
new->joincount = 1;
malloc_strcpy(&(new->nick), nick);
malloc_strcpy(&new->host, userhost);
new->serverhops = server_hops;
#ifdef WANT_USERLIST
new->userlist = lookup_userlevelc("*", userhost, channel, NULL);
new->shitlist = nickinshit(nick, userhost);
#endif
if (ischop > 0)
new->flags |= NICK_CHANOP;
if (voice > 0)
new->flags |= NICK_VOICE;
if (away)
{
if (strchr(away,'H'))
new->flags &= ~NICK_AWAY;
else
new->flags |= NICK_AWAY;
if (strchr(away, '*'))
new->flags |= NICK_IRCOP;
if (strchr(away, '%'))
new->flags |= NICK_HALFOP;
}
if (server1)
malloc_strcpy(&new->server, server1);
add_to_whowas_buffer(new, channel, server1, NULL);
}
}
return chan;
}
char *BX_get_channel_key (char *channel, int server)
{
ChannelList *tmp;
if ((tmp = lookup_channel(channel, server, 0)) != NULL)
return (tmp->key ? tmp->key : empty_string);
return empty_string;
}
/*
* recreate_mode: converts the bitmap representation of a channels mode into
* a string
*
* This malloces what it returns, but nothing that calls this function
* is expecting to have to free anything. Therefore, this function
* should not malloc what it returns. (hop)
*
* but this leads to horrible race conditions, so we add a bit to
* the channel structure, and cache the string value of mode, and
* the u_long value of the cached string, so that each channel only
* has one copy of the string. -mrg, june '94.
*/
char *BX_recreate_mode(ChannelList *chan)
{
int mode_pos = 0,
mode;
static char *s;
char buffer[BIG_BUFFER_SIZE + 1];
chan->i_mode = chan->mode;
buffer[0] = 0;
s = buffer;
mode = chan->mode;
if (!mode)
return NULL;
while (mode)
{
if (mode % 2)
*s++ = mode_str[mode_pos];
mode /= 2;
mode_pos++;
}
if (chan->key && *chan->key)
{
*s++ = ' ';
strcpy(s, chan->key);
s += strlen(chan->key);
}
if (chan->limit)
sprintf(s, " %d", chan->limit);
else
*s = 0;
malloc_strcpy(&chan->s_mode, buffer);
return chan->s_mode;
}
#ifdef COMPRESS_MODES
/* some structs to help along the process, NickList is way too much of a memory
hog */
typedef struct _UserChanModes {
struct _UserChanModes *next;
char *nick;
int o_ed;
int v_ed;
int deo_ed;
int dev_ed;
int b_ed;
int deb_ed;
} UserChanModes;
/*
* compress_modes: This will return a list of modes which removes duplicates
*
* for instance:
* +oooo Jordy Jordy Jordy Jordy
*
* would return:
* +o Jordy
*
* +oo-oo Sheik Jordy Sheik Jordy
*
* would return:
* -oo Sheik jordy
*
* also if *!*@* isn't banned on the channel
* -b *!*@*
*
* will return NULL
*
* This is a frigging ugly function and because I'm not going to sit and
* learn every shortcut function in irc, I don't care :)
*
* Written by Jordy (jordy@wserv.com)
*/
char *BX_do_compress_modes(ChannelList *chan, int server, char *channel, char *modes) {
int add = 0,
isbanned = 0,
isopped = 0,
isvoiced = 0,
mod = -1;
char *tmp = NULL,
*rest = NULL,
nmodes[16],
nargs[100];
UserChanModes *ucm = NULL,
*tucm = NULL;
BanList *tbl = NULL;
NickList *tnl = NULL;
/* now, modes contains the actual modes, and rest contains the arguments
to those modes */
if (!chan || !(modes = next_arg(modes, &rest)))
return NULL;
*nmodes = 0;
*nargs = 0;
for (; *modes && (strlen(nmodes) + 2) < sizeof nmodes; modes++)
{
isbanned = isopped = isvoiced = 0;
switch (*modes)
{
case '+':
add = 1;
break;
case '-':
add = 0;
break;
case 'o':
if (!(tmp = next_arg(rest, &rest)))
break;
if (!(tucm = (UserChanModes *)find_in_list((List **)&ucm, tmp, 0)))
{
tucm = (UserChanModes *) alloca(sizeof(UserChanModes));
memset(tucm, 0, sizeof(UserChanModes));
tucm->nick = LOCAL_COPY(tmp);
add_to_list((List **)&ucm, (List *)tucm);
}
tnl = find_nicklist_in_channellist(tmp, chan, 0);
if (tnl && (nick_isop(tnl) || tucm->o_ed))
isopped = 1;
else if (tnl)
isopped = 0;
if (add && !isopped)
{
tucm->o_ed = 1;
tucm->deo_ed = 0;
}
else if (!add && isopped)
{
tucm->o_ed = 0;
tucm->deo_ed = 1;
}
break;
case 'v':
if (!(tmp = next_arg(rest, &rest)))
break;
if (!(tucm = (UserChanModes *)find_in_list((List **)&ucm, tmp, 0)))
{
tucm = (UserChanModes *) alloca(sizeof(UserChanModes));
memset(tucm, 0, sizeof(UserChanModes));
tucm->nick = LOCAL_COPY(tmp);
add_to_list((List **)&ucm, (List *)tucm);
}
tnl = find_nicklist_in_channellist(tmp, chan, 0);
if (tnl && (nick_isvoice(tnl) || tucm->v_ed))
isvoiced = 1;
else if (tnl)
isvoiced = 0;
if (add && !isvoiced)
{
tucm->v_ed = 1;
tucm->dev_ed = 0;
}
else if (!add && isvoiced)
{
tucm->v_ed = 0;
tucm->dev_ed = 1;
}
break;
case 'b':
if (!(tmp = next_arg(rest, &rest)))
break;
if (!(tucm = (UserChanModes *)find_in_list((List **)&ucm, tmp, 0)))
{
tucm = (UserChanModes *) alloca(sizeof(UserChanModes));
memset(tucm, 0, sizeof(UserChanModes));
tucm->nick = LOCAL_COPY(tmp);
add_to_list((List **)&ucm, (List *)tucm);
}
if (!tucm->b_ed)
{
for (tbl = chan->bans; tbl && !isbanned; tbl = tbl->next)
{
if (!my_stricmp(tbl->ban, tmp))
isbanned = 1;
else
isbanned = 0;
}
}
if (add && !isbanned)
{
tucm->b_ed = 1;
tucm->deb_ed = 0;
}
else if (!add && isbanned)
{
tucm->b_ed = 0;
tucm->deb_ed = 1;
}
break;
case 'l':
case 'k':
tmp = next_arg(rest, &rest);
if (add)
{
if (mod == 1)
{
strcat(nmodes, "-");
strextend(nmodes, *modes, 1);
}
else
{
strcat(nmodes, "+");
strextend(nmodes, *modes, 1);
mod = 1;
}
}
else
{
if (!mod)
{
strcat(nmodes, "+");
strextend(nmodes, *modes, 1);
}
else
{
strcat(nmodes, "-");
strextend(nmodes, *modes, 1);
mod = 0;
}
}
if (tmp && *tmp)
strmopencat(nargs, sizeof(nargs)-1, space, tmp, NULL);
break;
case 'i':
case 's':
case 'n':
case 't':
case 'm':
{
if (add)
{
if (mod == 1)
strextend(nmodes, *modes, 1);
else
{
strextend(nmodes, '+', 1);
strextend(nmodes, *modes, 1);
mod = 1;
}
}
else
{
if (!mod)
strextend(nmodes, *modes, 1);
else
{
strextend(nmodes, '-', 1);
strextend(nmodes, *modes, 1);
mod = 0;
}
}
break;
}
}
}
/* modes which can be done multiple times are added here */
for (tucm = ucm; tucm && (strlen(nmodes) + 2) < sizeof nmodes;
tucm = tucm->next)
{
if (tucm->o_ed)
{
if (mod == 1)
strcat(nmodes, "o");
else
{
strcat(nmodes, "+o");
mod = 1;
}
strmopencat(nargs, sizeof(nargs)-1, space, tucm->nick, NULL);
}
else if (tucm->deo_ed)
{
if (!mod)
strcat(nmodes, "o");
else
{
strcat(nmodes, "-o");
mod = 0;
}
strmopencat(nargs, sizeof(nargs)-1, space, tucm->nick, NULL);
}
if (tucm->v_ed)
{
if (mod == 1)
strcat(nmodes, "v");
else
{
strcat(nmodes, "+v");
mod = 1;
}
strmopencat(nargs, sizeof(nargs)-1, space, tucm->nick, NULL);
}
else if (tucm->dev_ed)
{
if (!mod)
strcat(nmodes, "v");
else
{
strcat(nmodes, "-v");
mod = 0;
}
strmopencat(nargs, sizeof(nargs)-1, space, tucm->nick, NULL);
}
if (tucm->b_ed)
{
if (mod == 1)
strcat(nmodes, "b");
else
{
strcat(nmodes, "+b");
mod = 1;
}
strmopencat(nargs, sizeof(nargs)-1, space, tucm->nick, NULL);
}
else if (tucm->deb_ed)
{
if (!mod)
strcat(nmodes, "b");
else
{
strcat(nmodes, "-b");
mod = 0;
}
strmopencat(nargs, sizeof(nargs)-1, space, tucm->nick, NULL);
}
}
if (strlen(nmodes) || strlen(nargs))
return m_sprintf("%s%s", nmodes, nargs);
return NULL;
}
#endif
int BX_got_ops(int add, ChannelList *channel)
{
int have_op = 0;
register NickList *tmp;
int in_join = 0;
in_join = in_join_list(channel->channel, from_server);
if (add && add != channel->have_op && !in_join)
{
have_op = channel->have_op = add;
#ifdef WANT_USERLIST
for(tmp = next_nicklist(channel, NULL); tmp; tmp = next_nicklist(channel, tmp))
check_auto(channel->channel,tmp, channel);
#endif
if ((get_server_version(from_server) == Server2_8hybrid6))
send_to_server("MODE %s e", channel->channel);
}
else if (!add && add != channel->have_op && !in_join)
{
for(tmp = next_nicklist(channel, NULL); tmp; tmp = next_nicklist(channel, tmp))
tmp->sent_reop = tmp->sent_deop = tmp->sent_voice = tmp->sent_kick = 0;
}
return have_op;
}
/*
* apply_channel_modes
*
* This looks at a set of channel mode changes from a MODE command and
* applies them to the Channel structure (old decifer_mode()).
*/
static void apply_channel_modes(char *from, char *mode_str,
ChannelList *channel)
{
register char *person;
int add = 0;
int splitter = 0;
char *rest;
NickList *ThisNick = NULL;
BanList *new;
unsigned int value = 0;
int its_me = 0;
if (!(mode_str = next_arg(mode_str, &rest)))
return;
its_me = !my_stricmp(from, get_server_nickname(from_server)) ? 1 : 0;
splitter = wild_match("*.*.*", from);
for (; *mode_str; mode_str++)
{
switch (*mode_str)
{
case '+':
add = 1;
value = 0;
break;
case '-':
add = 0;
value = 0;
break;
case 'p':
value = MODE_PRIVATE;
break;
case 'l':
value = MODE_LIMIT;
if (add)
{
char *limit = next_arg(rest, &rest);
if (limit)
{
channel->limit = atoi(limit);
/* Setting +l 0 is the same as setting -l */
if (channel->limit == 0)
add = 0;
}
else
{
/* +l with no argument - broken server, just ignore
* it. */
value = 0;
}
}
else
{
channel->limit = 0;
}
break;
case 'a':
value = MODE_ANONYMOUS;
break;
case 't':
value = MODE_TOPIC;
break;
case 'i':
value = MODE_INVITE;
break;
case 'n':
value = MODE_MSGS;
break;
case 'r':
value = MODE_REGISTERED;
break;
case 's':
value = MODE_SECRET;
break;
case 'm':
value = MODE_MODERATED;
break;
case 'R':
value = MODE_RESTRICTED;
break;
case 'z':
value = MODE_Z;
break;
case 'h':
if (!(person = next_arg(rest, &rest)))
break;
if (!my_stricmp(person, get_server_nickname(from_server)))
{
channel->hop = add;
}
if ((ThisNick = find_nicklist_in_channellist(person, channel, 0)))
{
/* ThisNick->halfop=add;*/
if (add)
ThisNick->flags |= NICK_HALFOP;
else
ThisNick->flags &= ~NICK_HALFOP;
}
ThisNick = find_nicklist_in_channellist(from, channel, 0);
update_stats(add ? MODEHOPLIST: MODEDEHOPLIST, ThisNick, channel, splitter);
break;
case 'o':
{
if (!(person = next_arg(rest, &rest))) /* av 2.9 */
person = get_server_nickname(from_server);
if (!my_stricmp(person, get_server_nickname(from_server)))
{
got_ops(add, channel);
channel->have_op = add;
if (add)
do_hook(CHANOP_LIST, "%s", channel->channel);
}
ThisNick = find_nicklist_in_channellist(from, channel, 0);
update_stats(add ? MODEOPLIST: MODEDEOPLIST, ThisNick, channel, splitter);
if ((ThisNick = find_nicklist_in_channellist(person, channel, 0)))
{
if (add)
ThisNick->flags |= NICK_CHANOP;
else
ThisNick->flags &= ~NICK_CHANOP;
if (add)
{
if (ThisNick->sent_reop)
ThisNick->sent_reop--;
}
else if (ThisNick->sent_deop)
ThisNick->sent_deop--;
}
if (!its_me && channel->have_op)
{
if (add && splitter)
check_hack(person, channel, ThisNick, from);
#ifdef WANT_USERLIST
else if (!add)
check_prot(from, person, channel, NULL, ThisNick);
else if (ThisNick)
check_auto(channel->channel,ThisNick,channel);
#endif
}
break;
}
case 'c':
value = MODE_C;
if (add)
{
char *pass;
pass = next_arg(rest, &rest);
if (pass)
malloc_strcpy(&channel->chanpass, pass);
}
else
new_free(&channel->chanpass);
break;
case 'k':
value = MODE_KEY;
if (add)
malloc_strcpy(&channel->key, next_arg(rest, &rest));
else
{
if (rest)
next_arg(rest, &rest);
new_free(&channel->key);
}
channel->i_mode = -1;
break;
case 'v':
if ((person = next_arg(rest, &rest)))
{
if ((ThisNick = find_nicklist_in_channellist(person, channel, 0)))
{
if (add)
ThisNick->flags |= NICK_VOICE;
else
ThisNick->flags &= ~NICK_VOICE;
if (add)
{
if (ThisNick->sent_voice)
ThisNick->sent_voice--;
}
else
ThisNick->sent_voice = 0;
}
if (!my_stricmp(person, get_server_nickname(from_server)))
channel->voice = add;
}
break;
case 'b':
if (!(person = next_arg(rest, &rest)))
break;
ThisNick = find_nicklist_in_channellist(from, channel, 0);
update_stats(add?MODEBANLIST:MODEUNBANLIST, ThisNick, channel, splitter);
if (add)
{
ThisNick = find_nicklist_in_channellist(person, channel, 0);
if (!(new = (BanList *)find_in_list((List **)&channel->bans, person, 0)) || my_stricmp(person, new->ban))
{
new = (BanList *) new_malloc(sizeof(BanList));
malloc_strcpy(&new->ban, person);
add_to_list((List **)&channel->bans, (List *)new);
}
new->sent_unban = 0;
if (!new->setby)
malloc_strcpy(&new->setby, from?from:get_server_name(from_server));
new->time = now;
#ifdef WANT_USERLIST
if (!its_me && channel->have_op)
check_prot(from, person, channel, new, ThisNick);
#endif
}
else
{
if ((new = (BanList *)remove_from_list((List **)&channel->bans, person)))
{
new_free(&new->setby);
new_free(&new->ban);
new_free((char **)&new);
}
}
break;
case 'e':
if (!(person = next_arg(rest, &rest)))
break;
ThisNick = find_nicklist_in_channellist(from, channel, 0);
update_stats(add?MODEEBANLIST:MODEUNEBANLIST, ThisNick, channel, splitter);
if (add)
{
ThisNick = find_nicklist_in_channellist(person, channel, 0);
if (!(new = (BanList *)find_in_list((List **)&channel->exemptbans, person, 0)) || my_stricmp(person, new->ban))
{
new = (BanList *) new_malloc(sizeof(BanList));
malloc_strcpy(&new->ban, person);
add_to_list((List **)&channel->exemptbans, (List *)new);
}
new->sent_unban = 0;
if (!new->setby)
malloc_strcpy(&new->setby, from?from:get_server_name(from_server));
new->time = now;
}
else
{
if ((new = (BanList *)remove_from_list((List **)&channel->exemptbans, person)))
{
new_free(&new->setby);
new_free(&new->ban);
new_free((char **)&new);
}
}
break;
}
if (add)
channel->mode |= value;
else
channel->mode &= ~value;
}
#ifdef WANT_USERLIST
check_shit(channel);
#endif
flush_mode_all(channel);
}
/*
* get_channel_mode: returns the current mode string for the given channel
*/
char *BX_get_channel_mode(char *channel, int server)
{
ChannelList *tmp;
if ((tmp = lookup_channel(channel, server, CHAN_NOUNLINK)))
return recreate_mode(tmp);
return empty_string;
}
char *BX_get_channel_bans(char *channel, int server, int type_mode)
{
ChannelList *tmp;
if ((tmp = lookup_channel(channel, server, CHAN_NOUNLINK)))
{
BanList *b;
char *temp = NULL;
switch(type_mode)
{
case 1: /* ban */
for (b = tmp->bans; b; b = b->next)
m_s3cat(&temp, space, b->ban);
break;
case 2: /* ban who time */
for (b = tmp->bans; b; b = b->next)
{
m_s3cat(&temp, space, b->ban);
m_s3cat(&temp, space, b->setby);
m_s3cat(&temp, space, ltoa(b->time));
}
break;
case 3: /* exemptions [ts4] */
for (b = tmp->exemptbans; b; b = b->next)
m_s3cat(&temp, space, b->ban);
break;
}
return temp;
}
return m_strdup(empty_string);
}
/*
* update_channel_mode: This will modify the mode for the given channel
* according the the new mode given.
*/
void update_channel_mode(char *from, char *channel, int server, char *mode, ChannelList *tmp)
{
if (!tmp && channel)
{
tmp = lookup_channel(channel, server, CHAN_NOUNLINK);
}
if (tmp)
{
apply_channel_modes(from, mode, tmp);
}
}
/*
* is_channel_mode: returns the logical AND of the given mode with the
* channels mode. Useful for testing a channels mode
*/
int is_channel_mode(char *channel, int mode, int server_index)
{
ChannelList *tmp;
if ((tmp = lookup_channel(channel, server_index, CHAN_NOUNLINK)))
return (tmp->mode & mode);
return 0;
}
void BX_clear_bans(ChannelList *channel)
{
BanList *bans,
*next;
if (!channel)
return;
for (bans = channel->bans; bans; bans = next)
{
next = bans->next;
new_free(&bans->setby);
new_free(&bans->ban);
new_free((char **)&bans);
}
channel->bans = NULL;
for (bans = channel->exemptbans; bans; bans = next)
{
next = bans->next;
new_free(&bans->setby);
new_free(&bans->ban);
new_free((char **)&bans);
}
channel->exemptbans = NULL;
}
/* remove_channel()
*
* Removes the named channel from the channel list for the current context
* server. If the channel was the current channel for a window, this will
* select a new current channel if possible.
*
* Should be called in direct response to a message from the server indicating
* that we are no longer on the channel.
*/
void BX_remove_channel(const char *channel)
{
ChannelList *tmp;
if (*channel == '*')
return;
if ((tmp = lookup_channel(channel, from_server, CHAN_UNLINK)))
{
clear_bans(tmp);
clear_channel(tmp);
add_to_whowas_chan_buffer(tmp);
}
if (is_current_channel(channel, from_server, 1))
switch_channels(0, NULL);
xterm_settitle();
update_all_windows();
}
/*
* remove_from_channel: removes the given nickname from the given channel. If
* the nickname is not on the channel or the channel doesn't exist, nothing
* happens.
*/
void BX_remove_from_channel(char *channel, char *nick, int server, int netsplit, char *reason)
{
ChannelList *chan;
NickList *tmp = NULL;
extern char *last_split_server;
extern char *last_split_from;
char buf[BIG_BUFFER_SIZE+1];
char *server1 = NULL, *server2 = NULL;
if (netsplit && reason && *reason)
{
char *p = NULL;
strncpy(buf, reason, sizeof(buf)-1);
if ((p = strchr(buf, ' ')))
{
*p++ = '\0';
server2 = buf;
server1 = p;
}
if (server1 && !check_split_server(server1))
{
add_split_server(server1, server2, 0);
set_display_target(channel, LOG_CRAP);
malloc_strcpy(&last_split_server, server1);
malloc_strcpy(&last_split_from, server2);
if (do_hook(LLOOK_SPLIT_LIST, "%s %s", server2, server1))
{
char *s1, *s = NULL, *t = NULL;
if ((s = convert_to_keystr("WHOLEFT")))
t = LOCAL_COPY(s);
s = NULL;
if ((s1 = convert_to_keystr("CHANGE_TO_SPLIT")))
s = s1;
put_it("%s", convert_output_format(fget_string_var(FORMAT_NETSPLIT_FSET), "%s %s %s", update_clock(GET_TIME), server1, server2));
bitchsay("%s \002%s\002 to see who left \002%s\002 to change to [%s]", t ? "Press" : "", t ? t : "/wholeft", s ? s : "/server", server1);
}
reset_display_target();
}
}
if (channel)
{
if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)))
{
if ((tmp = find_nicklist_in_channellist(nick, chan, REMOVE_FROM_LIST)))
{
do_hook(NETSPLIT_LIST, "%d", netsplit);
add_to_whowas_buffer(tmp, channel, server1, server2);
if (netsplit)
{
if (server1 && strchr(server1, '*') && tmp->server)
server1 = tmp->server;
add_to_whosplitin_buffer(tmp, channel, server1, server2);
}
}
}
}
else
{
for (chan = get_server_channels(server); chan; chan = chan->next)
{
if ((tmp = find_nicklist_in_channellist(nick, chan, REMOVE_FROM_LIST)))
{
add_to_whowas_buffer(tmp, chan->channel, server1, server2);
if (netsplit)
{
if (server1 && strchr(server1, '*') && tmp->server)
server1 = tmp->server;
add_to_whosplitin_buffer(tmp, chan->channel, server1, server2);
}
}
}
}
}
static void handle_nickflood(char *old_nick, char *new_nick, register NickList *nick, register ChannelList *chan, int flood_time)
{
time_t floodtime = now - nick->bantime;
if ((!nick->bancount) || (nick->bancount && (floodtime > 3)))
{
if (!nick->sent_kick++)
send_to_server("KICK %s %s :\002Niq flood (%d nicks in %dsecs of %dsecs)\002", chan->channel, new_nick, get_cset_int_var(chan->csets, KICK_ON_NICKFLOOD_CSET), flood_time, get_cset_int_var(chan->csets, NICKFLOOD_TIME_CSET));
}
}
/*
* rename_nick: in response to a changed nickname, this looks up the given
* nickname on all you channels and changes it the new_nick
*/
void BX_rename_nick(char *old_nick, char *new_nick, int server)
{
register ChannelList *chan;
register NickList *tmp;
int t = 0;
for (chan = get_server_channels(server); chan; chan = chan->next)
{
if ((chan->server == server))
{
if ((tmp = find_nicklist_in_channellist(old_nick, chan, REMOVE_FROM_LIST)))
{
tmp->stat_nicks++;
if (chan->have_op && !isme(new_nick))
{
if (is_other_flood(chan, tmp, NICK_FLOOD, &t))
handle_nickflood(old_nick, new_nick, tmp, chan, t);
else if (get_cset_int_var(chan->csets, LAMELIST_CSET) && lame_list)
{
if (find_in_list((List **)&lame_list, new_nick, 0))
{
send_to_server("MODE %s -o+b %s %s!*@*", chan->channel, new_nick, new_nick);
send_to_server("KICK %s %s :\002Lame Nick detected\002", chan->channel, new_nick);
tmp->bancount++;
tmp->bantime = now;
}
}
}
check_orig_nick(new_nick);
xterm_settitle();
malloc_strcpy(&tmp->nick, new_nick);
add_nicklist_to_channellist(tmp, chan);
}
}
}
}
/*
* is_on_channel: returns true if the given nickname is in the given channel,
* false otherwise. Also returns false if the given channel is not on the
* channel list.
*/
int BX_is_on_channel(char *channel, int server, char *nick)
{
ChannelList *chan;
if (nick && (chan = lookup_channel(channel, server, CHAN_NOUNLINK)) && chan->connected)
if (find_nicklist_in_channellist(nick, chan, 0))
return 1;
return 0;
}
int BX_is_chanop(char *channel, char *nick)
{
ChannelList *chan;
NickList *Nick;
if (nick && (chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
{
if ((Nick = find_nicklist_in_channellist(nick, chan, 0)))
if (nick_isop(Nick))
return 1;
}
return 0;
}
int BX_is_halfop(char *channel, char *nick)
{
ChannelList *chan;
NickList *Nick;
if (nick && (chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
{
if ((Nick = find_nicklist_in_channellist(nick, chan, 0)))
if (nick_ishalfop(Nick))
return 1;
}
return 0;
}
char *is_chanoper(char *channel, char *nick)
{
ChannelList *chan;
NickList *Nick;
char *ret = NULL;
if (nick && (chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
{
char *n;
while ((n = next_in_comma_list(nick, &nick)))
{
if (!n || !*n) break;
if ((Nick = find_nicklist_in_channellist(n, chan, 0)))
m_s3cat(&ret, space, nick_isop(Nick) ?one:zero);
else
m_s3cat(&ret, space, zero);
}
}
return ret;
}
static void show_channel(ChannelList *chan)
{
NickList *tmp;
char *ptr, *s;
char buffer[BIG_BUFFER_SIZE * 10 + 1];
size_t nick_len = BIG_BUFFER_SIZE * 10;
int len = 0;
*buffer = 0;
s = recreate_mode(chan);
ptr = buffer;
for (tmp = next_nicklist(chan, NULL); tmp; tmp = next_nicklist(chan, tmp))
{
strlcpy(ptr, tmp->nick, nick_len);
if (tmp->host)
{
strlcat(ptr, "!", nick_len);
strlcat(ptr, tmp->host, nick_len);
}
strlcat(ptr, space, nick_len);
len = strlen(ptr);
nick_len -= len;
ptr += len;
if (nick_len <= 0)
break;
}
say("\t%s %c%s (%s) (Win: %d): %s",
chan->channel, s ? '+':' ',
s ? s : "<none>",
get_server_name(chan->server),
chan->window ? chan->window->refnum : -1,
buffer);
}
/* list_channels: displays your current channel and your channel list */
void list_channels(void)
{
ChannelList *tmp;
int server;
int shown_current = 0;
int shown_others = 0;
if (get_current_channel_by_refnum(0))
say("Current channel %s", get_current_channel_by_refnum(0));
else
say("No current channel for this window");
for (tmp = get_server_channels(get_window_server(0)); tmp; tmp = tmp->next)
{
show_channel(tmp);
shown_current = 1;
}
for (server = 0; server < server_list_size(); server++)
{
if (server == get_window_server(0))
continue;
for (tmp = get_server_channels(server); tmp; tmp = tmp->next)
{
if (!shown_others)
say("Other servers:");
show_channel(tmp);
shown_others = 1;
}
}
if (!shown_current && !shown_others)
say("You are not on any channels");
}
void switch_channels(char key, char *ptr)
{
ChannelList * tmp = NULL;
char *nc = get_current_channel_by_refnum(0);
if (from_server == -1 || !get_server_channels(from_server))
return;
if (nc)
if ((tmp = lookup_channel(nc, from_server, CHAN_NOUNLINK)))
tmp = tmp->next;
if (!tmp)
tmp = get_server_channels(from_server);
if (current_window->name && !strcmp(current_window->name, "oper_view"))
return;
for (; tmp; tmp = tmp->next)
{
if (tmp->server != from_server)
continue;
if (is_current_channel(tmp->channel, from_server, 0))
continue;
if (current_window == tmp->window)
{
set_current_channel_by_refnum(0, tmp->channel);
update_all_windows();
do_hook(CHANNEL_SWITCH_LIST, "%s", tmp->channel);
set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 0);
update_input(UPDATE_ALL);
#ifdef WANT_TCL
Tcl_SetVar(tcl_interp, "curchan", tmp->channel, TCL_GLOBAL_ONLY);
#endif
xterm_settitle();
return;
}
}
for (tmp = get_server_channels(from_server); tmp; tmp = tmp->next)
{
if (tmp->server != from_server)
continue;
if (is_current_channel(tmp->channel, from_server, 0))
continue;
if (current_window == tmp->window)
{
set_current_channel_by_refnum(0, tmp->channel);
update_all_windows();
do_hook(CHANNEL_SWITCH_LIST, "%s", tmp->channel);
set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 0);
update_input(UPDATE_ALL);
#ifdef WANT_TCL
Tcl_SetVar(tcl_interp, "curchan", tmp->channel, TCL_GLOBAL_ONLY);
#endif
xterm_settitle();
return;
}
}
}
void change_server_channels(int old, int new)
{
ChannelList *tmp;
if (new == old)
return;
if (new > -1 && (tmp = get_server_channels(new)))
tmp->server = new;
if (new > -1 && old > -1)
{
tmp = get_server_channels(old);
set_server_channels(new, tmp);
for (; tmp; tmp = tmp->next)
tmp->server = new;
set_server_channels(old, NULL);
}
}
void clear_channel_list(int server)
{
ChannelList *tmp = NULL,
*next;
Window *ptr = NULL;
while ((traverse_all_windows(&ptr)))
if (ptr->server == server && ptr->current_channel)
new_free(&ptr->current_channel);
for (tmp = get_server_channels(server); tmp; tmp = next)
{
next = tmp->next;
clear_channel(tmp);
add_to_whowas_chan_buffer(tmp);
}
set_server_channels(server, NULL);
clear_mode_list(server);
return;
}
/*
* reconnect_all_channels: used after you get disconnected from a server,
* clear each channel nickname list and re-JOINs each channel in the
* channel_list ..
*/
void reconnect_all_channels(int server)
{
ChannelList *tmp;
char *mode;
char *channel = NULL;
char *keys = NULL;
for (tmp = get_server_channels(server); tmp; tmp = tmp->next)
{
if ((mode = recreate_mode(tmp)))
add_to_mode_list(tmp->channel, server, mode);
add_to_join_list(tmp->channel, server, tmp->refnum);
m_s3cat(&channel, ",", tmp->channel);
m_s3cat(&keys, ",", tmp->key? tmp->key:"-");
clear_channel(tmp);
clear_bans(tmp);
tmp->server = server;
}
if (channel)
my_send_to_server(server, "JOIN %s %s", channel, keys ? keys : empty_string);
clear_channel_list(from_server);
new_free(&channel);
new_free(&keys);
reset_display_target();
}
char *what_channel(char *nick, int server)
{
ChannelList *tmp;
if (current_window->current_channel && is_on_channel(current_window->current_channel, current_window->server, nick))
return current_window->current_channel;
for (tmp = get_server_channels(from_server); tmp; tmp = tmp->next)
{
if (find_nicklist_in_channellist(nick, tmp, 0))
return tmp->channel;
}
return NULL;
}
ChannelList *walk_channels(char *nick, int init, int server)
{
static ChannelList *tmp = NULL;
if (init)
tmp = get_server_channels(server);
else if (tmp)
tmp = tmp->next;
for (;tmp ; tmp = tmp->next)
{
if (find_nicklist_in_channellist(nick, tmp, 0))
return tmp;
}
return NULL;
}
int BX_get_channel_oper(char *channel, int server)
{
ChannelList *chan;
if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)))
return chan->have_op;
return 1;
}
int BX_get_channel_halfop(char *channel, int server)
{
ChannelList *chan;
if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)))
return chan->hop;
return 1;
}
char *BX_fetch_userhost (int server, char *nick)
{
ChannelList *tmp = NULL;
NickList *user = NULL;
for (tmp = get_server_channels(server); tmp; tmp = tmp->next)
{
if (((user = (NickList *)find_nicklist_in_channellist(nick, tmp, 0))))
return user->host;
}
return NULL;
}
int BX_get_channel_voice(char *channel, int server)
{
ChannelList *chan;
if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)))
return chan->voice;
return 1;
}
extern void set_channel_window(Window *window, char *channel, int server)
{
ChannelList *tmp;
if (!channel || server < 0)
return;
for (tmp = get_server_channels(server); tmp; tmp = tmp->next)
{
if (!my_stricmp(channel, tmp->channel) && tmp->server == server)
{
tmp->window = window;
return;
}
}
}
extern char * BX_create_channel_list(Window *window)
{
ChannelList *chan;
char buffer[BIG_BUFFER_SIZE];
for (*buffer = 0, chan = get_server_channels(window->server); chan; chan = chan->next)
{
if (chan->server == from_server)
{
strlcat(buffer, chan->channel, sizeof buffer);
strlcat(buffer, space, sizeof buffer);
}
}
return m_strdup(buffer);
}
extern void channel_server_delete(int server)
{
ChannelList *tmp;
int i;
for (i = server + 1; i < server_list_size(); i++)
for (tmp = get_server_channels(i); tmp; tmp = tmp->next)
if (tmp->server >= server)
tmp->server--;
}
/* remove_from_join_list: called when mode and names have been received or
when access has been denied */
void remove_from_join_list(char *chan, int server)
{
struct joinlist *tmp,
*next,
*prev = NULL;
for (tmp = join_list; tmp; tmp = tmp->next)
{
next = tmp->next;
if (!my_stricmp(chan, tmp->chan) && tmp->server == server)
{
if (tmp == join_list)
join_list = next;
else
prev->next = next;
new_free(&tmp->chan);
new_free((char **)&tmp);
return;
}
else
prev = tmp;
}
}
/* get_win_from_join_list: returns the window refnum associated to the channel
we're trying to join */
int get_win_from_join_list(char *chan, int server)
{
struct joinlist *tmp;
int found = 0;
for (tmp = join_list; tmp; tmp = tmp->next)
{
if (!my_stricmp(tmp->chan, chan) && tmp->server == server)
found = tmp->winref;
}
return found;
}
/* get_chan_from_join_list: returns a pointer on the name of the first channel
entered into join_list for the specified server */
char *get_chan_from_join_list(int server)
{
struct joinlist *tmp;
char *found = NULL;
for (tmp = join_list; tmp; tmp = tmp->next)
{
if (tmp->server == server)
found = tmp->chan;
}
return found;
}
/* in_join_list: returns 1 if we're attempting to join the channel */
int in_join_list(char *chan, int server)
{
struct joinlist *tmp;
for (tmp = join_list; tmp; tmp = tmp->next)
{
if (!tmp->chan) continue;
if (!my_stricmp(tmp->chan, chan) && tmp->server == server)
return 1;
}
return 0;
}
void channel_sync(struct joinlist *tmp, char *channel)
{
double synch_time = time_since(&tmp->tv);
if (tmp->gotinfo & GOTNEW)
{
/* A channel that we just created. */
ChannelList *chan;
char *chanmode;
if ((chan = lookup_channel(channel, tmp->server, CHAN_NOUNLINK)))
if ((chanmode = get_cset_str_var(chan->csets, CHANMODE_CSET)))
my_send_to_server(tmp->server, "MODE %s :%s", channel, chanmode);
}
set_display_target(channel, LOG_CRAP);
if (do_hook(CHANNEL_SYNCH_LIST, "%s %1.3f", channel, synch_time))
bitchsay("Join to %s was synched in %1.3f secs!!", channel, synch_time);
#ifdef WANT_USERLIST
delay_check_auto(channel);
#endif
update_all_status(current_window, NULL, 0);
reset_display_target();
xterm_settitle();
#ifdef GUI
gui_update_nicklist(channel);
#endif
}
/* got_info: increments the gotinfo field when receiving names and mode
and removes the channel if both have been received */
int got_info(char *chan, int server, int type)
{
struct joinlist *tmp;
for (tmp = join_list; tmp; tmp = tmp->next)
if (!my_stricmp(tmp->chan, chan) && tmp->server == server)
{
int required = (GOTNAMES | GOTMODE | GOTBANS | GOTWHO);
int ver = get_server_version(server);
if ((ver == Server2_8ts4) || (ver == Server2_10))
required |= GOTEXEMPT;
tmp->gotinfo |= type;
if ((tmp->gotinfo & required) == required)
{
channel_sync(tmp, chan);
remove_from_join_list(chan, tmp->server);
return 1;
}
return 0;
}
return -1;
}
/* add_to_join_list: registers a channel we're trying to join */
void add_to_join_list(char *chan, int server, int winref)
{
struct joinlist *tmp;
for (tmp = join_list; tmp; tmp = tmp->next)
{
if (!my_stricmp(chan, tmp->chan) && (tmp->server == server) && (tmp->winref == winref))
{
tmp->winref = winref;
return;
}
}
tmp = (struct joinlist *) new_malloc(sizeof(struct joinlist));
tmp->chan = m_strdup(chan);
tmp->server = server;
tmp->gotinfo = 0;
tmp->winref = winref;
tmp->next = join_list;
get_time(&tmp->tv);
join_list = tmp;
}
static void add_to_mode_list(char *channel, int server, char *mode)
{
struct modelist *mptr;
if (!channel || !*channel || !mode || !*mode)
return;
mptr = (struct modelist *) new_malloc(sizeof(struct modelist));
mptr->chan = m_strdup(channel);
mptr->server = server;
mptr->mode =m_strdup(mode);
mptr->next = mode_list;
mode_list = mptr;
}
static void check_mode_list_join(char *channel, int server)
{
struct modelist *mptr;
if (!channel)
return;
for (mptr = mode_list; mptr; mptr = mptr->next)
{
if (!my_stricmp(mptr->chan, channel) && mptr->server == server)
{
my_send_to_server(mptr->server, "MODE %s %s", mptr->chan, mptr->mode);
remove_from_mode_list(channel, server);
return;
}
}
}
extern void remove_from_mode_list(char *channel, int server)
{
struct modelist *curr, *next, *prev = NULL;
for (next = mode_list; next; )
{
curr = next;
next = curr->next;
if (!my_stricmp(curr->chan, channel) && curr->server == server)
{
if (curr == mode_list)
mode_list = curr->next;
else
prev->next = curr->next;
prev = curr;
new_free(&curr->chan);
new_free(&curr->mode);
new_free((char **)&curr);
}
else
prev = curr;
}
}
extern void clear_mode_list(int server)
{
struct modelist *curr, *next, *prev = NULL;
for (next = mode_list; next; )
{
curr = next;
next = curr->next;
if (curr == mode_list)
mode_list = curr->next;
else
prev->next = curr->next;
prev = curr;
new_free(&curr->chan);
new_free(&curr->mode);
new_free((char **)&curr);
}
}
void BX_flush_channel_stats(void)
{
ChannelList *chan;
for (chan = get_server_channels(from_server); chan; chan = chan->next)
{
chan->stats_ops = 0;
chan->stats_dops = 0;
chan->stats_bans = 0;
chan->stats_unbans = 0;
chan->stats_sops = 0;
chan->stats_sdops = 0;
chan->stats_sbans = 0;
chan->stats_sunbans = 0;
chan->stats_topics = 0;
chan->stats_kicks = 0;
chan->stats_pubs = 0;
chan->stats_parts = 0;
chan->stats_signoffs = 0;
chan->stats_joins = 0;
chan->maxnicks = 0;
chan->maxnickstime = 0;
}
}
/*
* For any given window, re-assign all of the channels that are connected
* to that window.
*/
void unset_window_current_channel (Window *window)
{
ChannelList *tmp;
if (window->server <= -1)
return;
for (tmp = get_server_channels(window->server); tmp; tmp = tmp->next)
{
if (tmp->window == window && window->current_channel && !my_stricmp(tmp->channel, window->current_channel))
{
new_free(&window->current_channel);
tmp->window = NULL;
}
}
}
/*
* For any given window, re-assign all of the channels that are connected
* to that window.
*/
void move_window_channels (Window *window)
{
ChannelList *tmp;
if (window->server <= -1)
return;
for (tmp = get_server_channels(window->server); tmp; tmp = tmp->next)
{
if (tmp->window == window)
{
Window *w = NULL;
tmp->window = NULL;
while (traverse_all_windows(&w))
{
if (w->server == window->server && w != window)
{
tmp->window = w;
break;
}
}
}
}
}
void check_channel_limits()
{
int i;
ChannelList *chan;
for (i = 0; i < server_list_size(); i++)
{
for (chan = get_server_channels(i); chan; chan = chan->next)
{
if (!chan->have_op || !chan->csets || !chan->csets->set_auto_limit)
continue;
if (chan->totalnicks + chan->csets->set_auto_limit != chan->limit)
my_send_to_server(i, "MODE %s +l %d", chan->channel, chan->totalnicks + chan->csets->set_auto_limit);
}
}
}