/*
* 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 Michael Sandrof.
* Copyright (c) 1991, 1992 Troy Rollo.
* Copyright (c) 1992-2003 Matthew R. Green.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: names.c,v 1.59 2006/04/30 14:15:43 f Exp $
*/
#include "irc.h"
#include "ircaux.h"
#include "names.h"
#include "window.h"
#include "screen.h"
#include "server.h"
#include "lastlog.h"
#include "list.h"
#include "output.h"
#include "notify.h"
#include "vars.h"
/**************************** PATCHED by Flier ******************************/
#include "myvars.h"
#include "whowas.h"
#include <sys/time.h>
#include <unistd.h>
extern void ClearBans _((ChannelList *));
extern int CheckChannel _((char *, char *));
extern struct friends *FindMatch _((char *, char *));
extern struct autobankicks *FindShit _((char *, char *));
extern NickList *CheckJoiners _((char *, char *, int , ChannelList *));
extern void AwaySave _((char *, int));
extern int AddBan _((char *, char *, int, char *, int, time_t, ChannelList *));
extern int RemoveBan _((char *, int, ChannelList *));
extern void CheckPermBans _((ChannelList *));
extern void HandleGotOps _((char *, ChannelList *));
#ifdef SORTED_NICKS
extern int SortedCmp _((List *, List *));
#endif
extern int HashFunc _((char *));
extern NickList *find_in_hash _((ChannelList *, char *));
extern Window *FindWindowByPtr _((Window *));
extern void UpdateChanLogFName _((ChannelList *));
extern void ChannelLogReport _((char *, ChannelList *));
extern void ChannelLogSave _((char *, ChannelList *));
extern int RateLimitJoin _((int));
extern NickList *tabnickcompl;
/****************************************************************************/
/* from names.h */
static char mode_str[] = MODE_STRING;
static int same_channel _((ChannelList *, char *));
static void free_channel _((ChannelList **));
static void show_channel _((ChannelList *));
/**************************** PATCHED by Flier ******************************/
/*static void clear_channel _((ChannelList *));
static char *recreate_mode _((ChannelList *));
static int decifer_mode _((char *, u_long *, int *, NickList **, char **));*/
void clear_channel _((ChannelList *));
char *recreate_mode _((ChannelList *));
static int decifer_mode _((char *, int, u_long *, int *, NickList **, char **, ChannelList *, char *, char *, char *, char *));
void add_nick_to_hash _((ChannelList *, NickList *));
void remove_nick_from_hash _((ChannelList *, NickList *));
/****************************************************************************/
/* clear_channel: erases all entries in a nick list for the given channel */
/**************************** PATCHED by Flier ******************************/
/*static void*/
void
/****************************************************************************/
clear_channel(chan)
ChannelList *chan;
{
NickList *tmp,
*next;
for (tmp = chan->nicks; tmp; tmp = next)
{
next = tmp->next;
new_free(&(tmp->nick));
/**************************** PATCHED by Flier ******************************/
new_free(&(tmp->userhost));
/****************************************************************************/
new_free(&tmp);
}
chan->nicks = (NickList *) 0;
chan->status &= ~CHAN_NAMES;
/**************************** PATCHED by Flier ******************************/
ClearBans(chan);
/****************************************************************************/
}
/*
* we need this to deal with !channels.
*/
static int
same_channel(channel, chan2)
ChannelList *channel;
char *chan2;
{
size_t len, len2;
/* take the easy way out */
/**************************** PATCHED by Flier ******************************/
/*if (*channel->channel != '!' && *chan2 != '!')*/
if (*channel->channel != '!' || *chan2 != '!')
/****************************************************************************/
return (!my_stricmp(channel->channel, chan2));
/*
* OK, so what we have is channel = "!fooo" and chan2 = "!JUNKfoo".
*/
len = strlen(channel->channel);
len2 = strlen(chan2);
/* bail out on known stuff */
if (len > len2)
return (0);
if (len == len2)
return (!my_stricmp(channel->channel, chan2));
/*
* replace the channel name if we are the same!
*/
if (!my_stricmp(channel->channel + 1, chan2 + 1 + (len2 - len)))
{
malloc_strcpy(&channel->channel, chan2);
return (1);
}
return (0);
}
extern ChannelList *
lookup_channel(channel, server, do_unlink)
char *channel;
int server;
int do_unlink;
{
ChannelList *chan, *last = (ChannelList *) 0;
if (server == -1)
if ((server = primary_server) == -1)
return (ChannelList *) 0;
chan = server_list[server].chan_list;
while (chan)
{
if (chan->server == server && same_channel(chan, channel))
{
if (do_unlink == CHAN_UNLINK)
{
if (last)
last->next = chan->next;
else
server_list[server].chan_list = chan->next;
}
break;
}
last = chan;
chan = chan->next;
}
return chan;
}
/**************************** PATCHED by Flier ******************************/
void rename_channel(old_channel, new_channel)
char *old_channel;
char *new_channel;
{
ChannelList *chan;
if (!old_channel || !new_channel)
return;
if (!is_server_valid(from_server))
return;
chan = server_list[from_server].chan_list;
while (chan) {
if (!my_stricmp(chan->channel, old_channel))
break;
chan = chan->next;
}
if (chan) put_it("renaming [%s] to [%s]",old_channel,new_channel);
if (chan) malloc_strcpy(&(chan->channel), new_channel);
}
/****************************************************************************/
/*
* add_channel: adds the named channel to the channel list. If the channel
* is already in the list, its attributes are modified accordingly with the
* connected and copy parameters.
*/
void
/**************************** Patched by Flier ******************************/
/*add_channel(channel, server, connected, copy)*/
add_channel(channel, server, connected, copy, key, nowho)
/****************************************************************************/
char *channel;
int server;
int connected;
ChannelList *copy;
/**************************** Patched by Flier ******************************/
char *key;
int nowho;
/****************************************************************************/
{
ChannelList *new;
int do_add = 0;
/**************************** PATCHED by Flier ******************************/
int resetchan = 0;
WhowasChanList *whowaschan;
/****************************************************************************/
/*
* avoid adding channel "0"
*/
if (channel[0] == '0' && channel[1] == '\0')
return;
/**************************** PATCHED by Flier ******************************/
if ((whowaschan = check_whowas_chan_buffer(channel, 1))) {
if ((new = lookup_channel(channel, server, CHAN_UNLINK))) {
new_free(&(new->channel));
new_free(&(new->s_mode));
new_free(&(new->key));
new_free(&(new->topicstr));
new_free(&(new->topicwho));
new_free(&(new->modelock));
new_free(&(new->topiclock));
ClearBans(new);
new_free(&new);
}
new = whowaschan->channellist;
new->next = (ChannelList *) 0;
if ((new->window = is_bound(channel, server)) == (Window *) 0)
new->window = curr_scr_win;
do_add = 1;
add_to_list((List **) &server_list[server].chan_list, (List *) new);
new_free(&whowaschan);
}
else
/****************************************************************************/
if ((new = lookup_channel(channel, server, CHAN_NOUNLINK)) == (ChannelList *) 0)
{
new = (ChannelList *) new_malloc(sizeof(ChannelList));
new->channel = (char *) 0;
new->status = 0;
new->key = (char *) 0;
new->nicks = (NickList *) 0;
new->s_mode = empty_string;
malloc_strcpy(&new->channel, channel);
new->mode = 0;
new->limit = 0;
if ((new->window = is_bound(channel, server)) == (Window *) 0)
new->window = curr_scr_win;
do_add = 1;
add_to_list((List **) &server_list[server].chan_list, (List *) new);
/**************************** PATCHED by Flier ******************************/
new->creationtime = time((time_t *) 0);
new->modelock = (char *) 0;
new->topiclock = (char *) 0;
new->chanlogfpath = (char *) 0;
resetchan = 1;
/****************************************************************************/
}
else
{
/**************************** Patched by Flier ******************************/
if (!(new->nicks)) resetchan = 1;
/****************************************************************************/
if (new->connected != CHAN_LIMBO && new->connected != CHAN_JOINING)
yell("--- add_channel: add_channel found channel not CHAN_LIMBO/JOINING: %s", new->channel);
}
if (do_add || (connected == CHAN_JOINED))
{
new->server = server;
/**************************** PATCHED by Flier ******************************/
new->status = 0;
new->gotbans = 0;
new->repeatexceptions = 0;
new->gotwho = nowho;
new->mode = 0;
new->limit = 0;
new_free(&new->key);
new_free(&new->s_mode);
new->s_mode = empty_string;
gettimeofday(&(new->time), NULL);
if (resetchan) {
int i;
/* yay for ircII channel join handling, why is this called twice ? */
if (!connected) {
new->modelock = (char *) 0;
new->topiclock = (char *) 0;
}
new->pluso = 0; new->minuso = 0; new->plusb = 0;
new->minusb = 0; new->topic = 0; new->kick = 0;
new->pub = 0; new->servpluso = 0; new->servminuso = 0;
new->servplusb = 0; new->servminusb = 0;
new->servplush = 0; new->servminush = 0;
new->plush = 0; new->minush = 0;
new->AutoRejoin = AutoRejoin ? CheckChannel(channel, AutoRejoinChannels) : 0;
new->MDopWatch = MDopWatch ? CheckChannel(channel, MDopWatchChannels) : 0;
new->ShowFakes = ShowFakes ? CheckChannel(channel, ShowFakesChannels) : 0;
new->KickOnFlood = KickOnFlood ? CheckChannel(channel, KickOnFloodChannels) : 0;
new->KickWatch = KickWatch ? CheckChannel(channel, KickWatchChannels) : 0;
new->NHProt = NHProt ? CheckChannel(channel, NHProtChannels) : 0;
new->NickWatch = NickWatch ? CheckChannel(channel, NickWatchChannels) : 0;
new->ShowAway = ShowAway ? CheckChannel(channel, ShowAwayChannels) : 0;
new->KickOps = KickOps ? CheckChannel(channel, KickOpsChannels) : 0;
new->KickOnBan = KickOnBan ? CheckChannel(channel, KickOnBanChannels) : 0;
new->Bitch = Bitch ? CheckChannel(channel, BitchChannels) : 0;
new->FriendList = FriendList ? CheckChannel(channel, FriendListChannels) : 0;
#ifdef EXTRAS
new->IdleKick =IdleKick ? CheckChannel(channel, IdleKickChannels) : 0;
if (new->IdleKick) new->IdleKick = IdleKick;
#endif
new->CompressModes = CompressModes ? CheckChannel(channel, CompressModesChannels) : 0;
new->BKList = BKList ? CheckChannel(channel, BKChannels) : 0;
new->ChanLog = ChanLog ? CheckChannel(channel, ChanLogChannels) : 0;
if (new->ChanLog) UpdateChanLogFName(new);
new->TryRejoin = 0;
new->banlist = NULL;
new->topicstr = NULL;
new->topicwho = NULL;
for (i = 0; i < HASHTABLESIZE; i++) new->nickshash[i] = (struct hashstr *) 0;
}
/****************************************************************************/
clear_channel(new);
}
if (copy)
{
new->mode = copy->mode;
new->limit = copy->limit;
new->window = copy->window;
malloc_strcpy(&new->key, copy->key);
}
new->connected = connected;
/**************************** Patched by Flier ******************************/
if (key && *key) malloc_strcpy(&new->key, key);
/****************************************************************************/
if ((connected == CHAN_JOINED) && !is_current_channel(channel, server, 0))
{
int flag = 1;
Window *tmp, *expected,
*possible = (Window *) 0;
expected = new->window;
while ((tmp = traverse_all_windows(&flag)))
{
/**************************** PATCHED by Flier ******************************/
if (tmp->name && !strcmp(tmp->name, "OV")) continue;
/****************************************************************************/
if (tmp->server == server)
{
if (tmp == expected)
{
set_channel_by_refnum(tmp->refnum, channel);
new->window = tmp;
update_all_status();
return;
}
else if (!possible)
possible = tmp;
}
}
if (possible)
{
set_channel_by_refnum(possible->refnum, channel);
new->window = possible;
update_all_status();
return;
}
set_channel_by_refnum(0, channel);
new->window = curr_scr_win;
}
update_all_windows();
}
/**************************** PATCHED by Flier ******************************/
/* adds given nick to hash table */
void add_nick_to_hash(chan,nick)
ChannelList *chan;
NickList *nick;
{
int i=HashFunc(nick->nick);
struct hashstr *hashnew;
struct hashstr *tmphash;
if (find_in_hash(chan,nick->nick)) return;
if ((hashnew=(struct hashstr *) new_malloc(sizeof(struct hashstr)))) {
hashnew->next=(struct hashstr *) 0;
hashnew->nick=nick;
for (tmphash=chan->nickshash[i];tmphash && tmphash->next;) tmphash=tmphash->next;
if (tmphash) tmphash->next=hashnew;
else chan->nickshash[i]=hashnew;
}
}
/****************************************************************************/
/*
* 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)
*/
/**************************** PATCHED by Flier ******************************/
/*void
add_to_channel(channel, nick, server, oper, voice)
char *channel;
char *nick;
int server;
int oper;
int voice;*/
ChannelList *add_to_channel(channel, nick, server, oper, halfop, voice, userhost,tmpchan)
char *channel;
char *nick;
int server;
int oper;
int halfop;
int voice;
char *userhost;
ChannelList *tmpchan;
/****************************************************************************/
{
NickList *new;
ChannelList *chan;
int ishalfop = halfop;
int ischop = oper;
int hasvoice = voice;
/**************************** PATCHED by Flier ******************************/
char tmpbuf[mybufsize / 4];
time_t timenow;
NickList *tmp;
WhowasList *whowas;
/****************************************************************************/
/**************************** PATCHED by Flier ******************************/
/*if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)))*/
if (tmpchan) chan = tmpchan;
else chan = lookup_channel(channel,server, CHAN_NOUNLINK);
if (chan)
/****************************************************************************/
{
/**************************** Patched by Flier ******************************/
char *tmpnick = nick;
/* support for @+%nick */
while (tmpnick && *tmpnick) {
if (*tmpnick == '+') {
hasvoice = 1;
nick++;
}
else if (*tmpnick == '%') {
ishalfop = 1;
nick++;
}
else if (*tmpnick == '@') {
ischop = 1;
nick++;
}
else if (*tmpnick == '&' || *tmpnick == '~') {
nick++;
}
tmpnick++;
}
if (ishalfop && !my_stricmp(nick, get_server_nickname(server)))
chan->status |= CHAN_HALFOP;
if (hasvoice && !my_stricmp(nick, get_server_nickname(server)))
chan->status |= CHAN_VOICE;
if (ischop && !my_stricmp(nick, get_server_nickname(server)) && !((chan->status & CHAN_NAMES) && (chan->status & CHAN_MODE)))
{
char *mode = recreate_mode(chan);
if (*mode) {
int old_server = from_server;
from_server = server;
send_to_server("MODE %s %s", chan->channel, mode);
from_server = old_server;
}
chan->status |= CHAN_CHOP;
}
/*if (*nick == '+')
{
hasvoice = 1;
nick++;
}
if (*nick == '@')
{
nick++;
if (!my_stricmp(nick, get_server_nickname(server)) && !((chan->status & CHAN_NAMES) && (chan->status & CHAN_MODE)))
{
char *mode = recreate_mode(chan);
if (*mode)
{
int old_server = from_server;
from_server = server;
send_to_server("MODE %s %s", chan->channel, mode);
from_server = old_server;
}
chan->status |= CHAN_CHOP;
}
ischop = 1;
}*/
/****************************************************************************/
/**************************** PATCHED by Flier ******************************/
/*if ((new = (NickList *) remove_from_list((List **) &(chan->nicks), nick)))
{
new_free(&(new->userhost));
remove_nick_from_hash(chan,new);
new_free(&(new->nick));
new_free(&new);
}
new = (NickList *) new_malloc(sizeof(NickList));
new->nick = (char *) 0;
new->chanop = ischop;
new->halfop = ishalfop;
new->hasvoice = hasvoice;
malloc_strcpy(&(new->nick), nick);
add_to_list((List **) &(chan->nicks), (List *) new);*/
tmp = (NickList *) remove_from_list((List **) &(chan->nicks),
nick);
if (userhost &&
(whowas = check_whowas_buffer(nick, userhost, channel, 1))) {
new = whowas->nicklist;
new_free(&whowas);
snprintf(tmpbuf, sizeof(tmpbuf), "%s!%s", nick, userhost);
if (!(new->frlist &&
wild_match(new->frlist->userhost, tmpbuf) &&
CheckChannel(new->frlist->channels, channel)))
new->frlist = (struct friends *)
FindMatch(tmpbuf, channel);
if (!(new->shitlist &&
wild_match(new->shitlist->userhost, tmpbuf) &&
CheckChannel(new->shitlist->channels, channel)))
new->shitlist = (struct autobankicks *)
FindShit(tmpbuf, channel);
}
else {
new = (NickList *) new_malloc(sizeof(NickList));
new->nick = (char *) 0;
new->userhost = (char *) 0;
new->frlist = (struct friends *) 0;
new->shitlist = (struct autobankicks *) 0;
new->pluso = tmp ? tmp->pluso : 0;
new->minuso = tmp ? tmp->minuso : 0;
new->plusb = tmp ? tmp->plusb : 0;
new->minusb = tmp ? tmp->minusb : 0;
new->kick = tmp ? tmp->kick : 0;
new->nickc = tmp ? tmp->nickc : 0;
new->publics = tmp ? tmp->publics : 0;
if (userhost) {
snprintf(tmpbuf, sizeof(tmpbuf), "%s!%s", nick, userhost);
malloc_strcpy(&(new->userhost), userhost);
new->frlist = (struct friends *)
FindMatch(tmpbuf, channel);
new->shitlist = (struct autobankicks *)
FindShit(tmpbuf, channel);
}
}
if (tmp) {
new_free(&(tmp->userhost));
remove_nick_from_hash(chan, tmp);
new_free(&(tmp->nick));
new_free(&tmp);
}
malloc_strcpy(&(new->nick), nick);
new->chanop = ischop;
new->halfop = ishalfop;
new->hasvoice = hasvoice;
new->curo = 0;
new->curk = 0;
new->curn = 0;
timenow = time((time_t *) 0);
new->deopt = timenow;
new->kickt = timenow;
new->nickt = timenow;
new->lastmsg = timenow;
new->deopp = 0;
new->kickp = 0;
new->nickp = 0;
#ifdef SORTED_NICKS
add_to_list_ext((List **) &(chan->nicks), (List *) new, SortedCmp);
#else
add_to_list((List **) &(chan->nicks), (List *) new);
#endif
add_nick_to_hash(chan, new);
/****************************************************************************/
}
notify_mark(nick, 1, 0);
/**************************** PATCHED by Flier ******************************/
return(chan);
/****************************************************************************/
}
/*
* recreate_mode: converts the bitmap representation of a channels mode into
* a string
*/
/**************************** PATCHED by Flier ******************************/
/*static char **/
char *
/****************************************************************************/
recreate_mode(chan)
ChannelList *chan;
{
int mode_pos = 0,
mode;
static char *s;
char buffer[BIG_BUFFER_SIZE+1];
buffer[0] = '\0'; /* paranoia */
s = buffer;
mode = chan->mode;
while (mode)
{
if (mode % 2)
*s++ = mode_str[mode_pos];
mode /= 2;
mode_pos++;
}
if (chan->key && !get_int_var(HIDE_CHANNEL_KEYS_VAR))
{
*s++ = ' ';
/**************************** Patched by Flier ******************************/
/*strcpy(s, chan->key);*/
strmcpy(s, chan->key, sizeof(buffer) - (s - buffer));
/****************************************************************************/
s += strlen(chan->key);
}
if (chan->limit)
snprintf(s, sizeof(buffer) - (s - buffer), " %d", chan->limit);
else
*s = '\0';
malloc_strcpy(&chan->s_mode, buffer);
return chan->s_mode;
}
/*
* decifer_mode: This will figure out the mode string as returned by mode
* commands and convert that mode string into a one byte bit map of modes
*/
/**************************** PATCHED by Flier ******************************/
/*static int
decifer_mode(mode_string, mode, chop, nicks, key)
char *mode_string;
u_long *mode;
char *chop;
NickList **nicks;
char **key;*/
static int
decifer_mode(mode_string,modelen,mode,chop,nicks,key,chan,from,userhost,nethacks,servmodes)
char *mode_string;
int modelen;
u_long *mode;
int *chop;
NickList **nicks;
char **key;
ChannelList *chan;
char *from;
char *userhost;
char *nethacks;
char *servmodes;
/****************************************************************************/
{
char *limit = 0;
/**************************** PATCHED by Flier ******************************/
/*char *person;*/
char *person = NULL;
/****************************************************************************/
int add = 0;
int limit_set = 0;
int limit_reset = 0;
char *rest,
*the_key;
NickList *ThisNick;
u_long value = 0;
/**************************** PATCHED by Flier ******************************/
char *mynick = get_server_nickname(parsing_server_index);
int check = from ? 1 : 0;
int gotops = 0;
int isitme = check ? !my_stricmp(from, mynick) : 0;
int isserver = check ? (strchr(from, '.') != NULL) : 0;
int max = get_int_var(MAX_MODES_VAR);
int deopped = 0;
int servadd = -1;
int compadd = -1;
int minusban = 0;
int hadops = !HAS_OPS(*chop);
int privs;
int isprot = 0;
int count = 0;
int whowasdone = 0;
int server = parsing_server_index;
int exception;
int compmodelen = 0, compmodemax;
int servmodeslen = 0, servmodesmax;
char *arg;
char tmpbuf[mybufsize / 2];
char nhdeop[mybufsize / 4];
char modebuf[mybufsize / 32];
char servline[mybufsize / 2];
char lastdeop[mybufsize / 4];
char lastvoice[mybufsize / 4];
char compmode[mybufsize / 32];
char compline[mybufsize / 2];
char tmpbufmode[mybufsize / 2];
char tmporigmode[mybufsize / 2];
/* has to be the same as nethacks */
char nethackbuf[mybufsize / 2];
char *origmode = mode_string;
char *compmodeadd = compmode;
char *servmodeadd = servmodes;
time_t timenow = time(NULL);
NickList *joiner = NULL;
NickList *tmpjoiner = NULL;
WhowasList *whowas;
servmodesmax = sizeof(servmodes) - 1;
compmodemax = sizeof(compmode) - 1;
*nethackbuf = '\0';
if (nethacks) *nethacks = '\0';
if (check) {
if (isserver) userhost = NULL;
*servmodeadd = '\0';
*tmpbufmode = '\0';
*servline = '\0';
*lastdeop = '\0';
*lastvoice = '\0';
*nhdeop = '\0';
*compline = '\0';
*compmodeadd = '\0';
tmpjoiner = CheckJoiners(from, chan->channel, server, chan);
if (tmpjoiner) {
if (tmpjoiner->curo == 0) tmpjoiner->deopp = 0;
if (timenow-tmpjoiner->deopt >= MDopTimer) {
tmpjoiner->curo = 0;
tmpjoiner->deopp = 0;
tmpjoiner->deopt = timenow;
}
if (tmpjoiner->userhost && tmpjoiner->frlist)
isprot = (tmpjoiner->frlist->privs) & (FLPROT | FLGOD);
}
if (!(chan->CompressModes)) strmcpy(tmporigmode, mode_string, sizeof(tmporigmode));
}
/****************************************************************************/
if (!(mode_string = next_arg(mode_string, &rest)))
return -1;
for (; *mode_string; mode_string++)
{
/**************************** PATCHED by Flier ******************************/
if (*mode_string != 'o' && *mode_string != '+' && *mode_string != '-') {
if (check && isserver) {
if (servadd != add) {
if (servmodeslen < servmodesmax) {
if (add) *servmodeadd ++= '+';
else *servmodeadd ++= '-';
servmodeslen++;
}
servadd = add;
}
if (servmodeslen < servmodesmax) {
*servmodeadd ++= *mode_string;
servmodeslen++;
}
}
}
if (check && chan->CompressModes) {
if (*mode_string == 'a' || *mode_string == 'i' || *mode_string == 'k' ||
*mode_string == 'l' || *mode_string == 'm' || *mode_string == 'n' ||
*mode_string == 'p' || *mode_string == 'q' || *mode_string == 's' ||
*mode_string == 't' || *mode_string == 'c' || *mode_string == 'R' ||
*mode_string == 'I' || *mode_string == 'S' || *mode_string == 'g' ||
*mode_string == 'z' || *mode_string == 'Q') {
if (compadd != add) {
if (compmodelen < compmodemax) {
if (add) *compmodeadd ++= '+';
else *compmodeadd ++= '-';
compmodelen++;
}
compadd = add;
}
if (compmodelen < compmodemax) {
*compmodeadd ++= *mode_string;
compmodelen++;
}
}
}
/****************************************************************************/
switch (*mode_string)
{
case '+':
add = 1;
value = 0;
break;
case '-':
add = 0;
value = 0;
break;
case 'a':
value = MODE_ANONYMOUS;
break;
case 'c':
value = MODE_COLOURLESS;
break;
case 'i':
value = MODE_INVITE;
break;
/**************************** PATCHED by Flier ******************************/
case 'g':
value = MODE_ALLINVITE;
break;
case 'Q':
value = MODE_NOFORWARD;
break;
case 'z':
value = MODE_REDUCEMODERATED;
break;
/****************************************************************************/
case 'k':
value = MODE_KEY;
the_key = next_arg(rest, &rest);
if (add)
malloc_strcpy(key, the_key);
else
new_free(key);
/**************************** PATCHED by Flier ******************************/
if (!the_key) the_key = empty_string;
if (check && isserver) {
strmcat(servline, the_key, sizeof(servline));
strmcat(servline, " ", sizeof(servline));
}
if (check && chan->CompressModes) {
strmcat(compline, the_key, sizeof(compline));
strmcat(compline, " ", sizeof(compline));
}
/****************************************************************************/
break;
case 'l':
value = MODE_LIMIT;
if (add)
{
limit_set = 1;
if (!(limit = next_arg(rest, &rest)))
limit = empty_string;
else if (0 == strncmp(limit, irczero, 1))
limit_reset = 1, limit_set = 0, add = 0;
}
else
limit_reset = 1;
/**************************** PATCHED by Flier ******************************/
if (check && isserver && add) {
strmcat(servline, limit, sizeof(servline));
strmcat(servline, " ", sizeof(servline));
}
if (check && chan->CompressModes) {
if (add) {
strmcat(compline, limit, sizeof(compline));
strmcat(compline, " ", sizeof(compline));
}
}
/****************************************************************************/
break;
case 'm':
value = MODE_MODERATED;
break;
/**************************** Patched by Flier ******************************/
/* half-op code by braneded */
case 'h':
if ((person = next_arg(rest, &rest)) && !my_stricmp(person, mynick)) {
if (add) {
/* we can only have one of ohv on a hybrid7 server.
+v, +h, -h != +v */
if (get_server_version(server) == Server2_11)
*chop &= ~CHAN_VOICE;
*chop |= CHAN_HALFOP;
if (check && hadops) gotops = 1;
}
else
*chop &= ~CHAN_HALFOP;
}
ThisNick = find_in_hash(chan, person);
if (!person) person = empty_string;
if (check && chan->CompressModes && ThisNick) {
if ((add && !(ThisNick->halfop)) ||
(!add && ThisNick->halfop)) {
if (compadd != add) {
if (compmodelen < compmodemax) {
if (add) *compmodeadd ++= '+';
else *compmodeadd ++= '-';
compmodelen++;
}
compadd = add;
}
if (compmodelen < compmodemax) {
*compmodeadd ++= *mode_string;
compmodelen++;
}
strmcat(compline, person, sizeof(compline));
strmcat(compline, " ", sizeof(compline));
}
}
if (isserver) {
if (!add) {
if (servadd != add) {
if (servmodeslen < servmodesmax) {
if (add) *servmodeadd ++= '+';
else *servmodeadd ++= '-';
servmodeslen++;
}
servadd = add;
}
if (servmodeslen < servmodesmax) {
*servmodeadd ++= *mode_string;
servmodeslen++;
}
strmcat(servline, person, sizeof(servline));
strmcat(servline, " ", sizeof(servline));
}
}
if (ThisNick) {
ThisNick->halfop = add;
if (add && get_server_version(server) == Server2_11)
ThisNick->hasvoice = 0;
}
if (check && tmpjoiner) {
if (add) tmpjoiner->plush++;
else tmpjoiner->minush++;
}
if (isserver) {
if (add) {
chan->servplush++;
strmcat(servline, person, sizeof(servline));
strmcat(servline, " ", sizeof(servline));
} else chan->servminush++;
}
if (add) chan->plush++;
else chan->minush++;
break;
/****************************************************************************/
case 'o':
/**************************** PATCHED by Flier ******************************/
/*if ((person = next_arg(rest, &rest)) && !my_stricmp(person, get_server_nickname(from_server))) {
if (add) {
*chop |= CHAN_CHOP;
else
*chop &= ~CHAN_CHOP;
}*/
if ((person = next_arg(rest, &rest)) && !my_stricmp(person, mynick)) {
if (add) {
/* we can only have one of ohv on a hybrid7 server.
+h, +o, -o != +h */
if (get_server_version(server) == Server2_11)
*chop &= ~(CHAN_HALFOP | CHAN_VOICE);
*chop |= CHAN_CHOP;
if (check && hadops) gotops = 1;
}
else
*chop &= ~CHAN_CHOP;
}
/****************************************************************************/
/**************************** PATCHED by Flier ******************************/
/*ThisNick = (NickList *) list_lookup((List **) nicks, person, !USE_WILDCARDS, !REMOVE_FROM_LIST);*/
ThisNick = find_in_hash(chan, person);
if (!person) person = empty_string;
if (check) {
if (tmpjoiner) {
if (add) tmpjoiner->pluso++;
else {
tmpjoiner->minuso++;
tmpjoiner->curo++;
}
}
if (isserver) {
if (!add) {
if (servadd != add) {
if (servmodeslen < servmodesmax) {
if (add) *servmodeadd ++= '+';
else *servmodeadd ++= '-';
servmodeslen++;
}
servadd = add;
}
if (servmodeslen < servmodesmax) {
*servmodeadd ++= *mode_string;
servmodeslen++;
}
strmcat(servline, person, sizeof(servline));
strmcat(servline, " ", sizeof(servline));
}
else {
if (chan->NHProt && chan->FriendList) {
if (!(ThisNick && ThisNick->frlist && ThisNick->frlist->privs)) {
strmcat(nhdeop, " -o ", sizeof(nhdeop));
strmcat(nhdeop, person, sizeof(nhdeop));
}
}
strmcat(nethackbuf, person, sizeof(nethackbuf));
strmcat(nethackbuf, " ", sizeof(nethackbuf));
}
if (add) chan->servpluso++;
else chan->servminuso++;
}
if (check && chan->CompressModes && ThisNick) {
if ((add && !(ThisNick->chanop)) ||
(!add && ThisNick->chanop)) {
if (compadd != add) {
if (compmodelen < compmodemax) {
if (add) *compmodeadd ++= '+';
else *compmodeadd ++= '-';
compmodelen++;
}
compadd = add;
}
if (compmodelen < compmodemax) {
*compmodeadd ++= *mode_string;
compmodelen++;
}
strmcat(compline, person, sizeof(compline));
strmcat(compline, " ", sizeof(compline));
}
}
if (add) {
chan->pluso++;
minusban = 1;
if (ThisNick && chan->BKList) {
if ((ThisNick->shitlist && (ThisNick->shitlist->shit) & SLDEOP)
|| (chan->Bitch && !isitme && !(isprot & FLGOD) &&
(!ThisNick->frlist || !((ThisNick->frlist->privs) & (FLOP | FLAUTOOP | FLINSTANT))) &&
my_stricmp(mynick, ThisNick->nick))) {
count++;
strmcat(modebuf, "-o", sizeof(modebuf));
strmcat(tmpbufmode, " ", sizeof(tmpbufmode));
strmcat(tmpbufmode, ThisNick->nick, sizeof(tmpbufmode));
}
}
}
else {
chan->minuso++;
if (!isitme && ThisNick && ThisNick->userhost &&
ThisNick->chanop && chan->FriendList) {
if (ThisNick->frlist) privs = ThisNick->frlist->privs;
else privs = 0;
if ((privs & (FLPROT | FLGOD)) && (privs & FLOP)
&& my_stricmp(from, ThisNick->nick)
&& !CheckChannel(lastdeop, ThisNick->nick)
&& !(!(privs & FLGOD) && (isprot & FLGOD))) {
if (away_set || LogOn || (chan && chan->ChanLog)) {
snprintf(tmpbuf,sizeof(tmpbuf),"%s (%s) has been deopped on channel %s by %s",
ThisNick->nick, ThisNick->userhost,
chan->channel, from);
if (!isserver) {
strmcat(tmpbuf, " (", sizeof(tmpbuf));
strmcat(tmpbuf, userhost, sizeof(tmpbuf));
strmcat(tmpbuf, ")", sizeof(tmpbuf));
}
if (away_set || LogOn) AwaySave(tmpbuf, SAVEPROT);
if (chan && chan->ChanLog) ChannelLogSave(tmpbuf, chan);
}
if (*chop & CHAN_CHOP) {
if (!isserver && (privs & FLGOD) && !(isprot & FLGOD)) {
count++;
strmcat(modebuf, "-o", sizeof(modebuf));
strmcat(tmpbufmode, " ", sizeof(tmpbufmode));
strmcat(tmpbufmode, from, sizeof(tmpbufmode));
deopped = 1;
}
if (count == max) {
send_to_server("MODE %s %s %s",
chan->channel, modebuf,
tmpbufmode);
*tmpbufmode = '\0';
*modebuf = '\0';
count = 0;
}
if ((privs & FLGOD) || ((privs & FLPROT) && !(isprot & FLGOD))) {
count++;
strmcat(modebuf, "+o", sizeof(modebuf));
strmcat(tmpbufmode, " ", sizeof(tmpbufmode));
strmcat(tmpbufmode, ThisNick->nick, sizeof(tmpbufmode));
}
}
if (*lastdeop) strmcat(lastdeop, ",", sizeof(lastdeop));
strmcat(lastdeop, ThisNick->nick, sizeof(lastdeop));
}
}
}
}
if (ThisNick && add && !(ThisNick->chanop)) {
ThisNick->curo = 0;
ThisNick->deopp = 0;
ThisNick->deopt = timenow;
}
/****************************************************************************/
if (ThisNick)
{
ThisNick->chanop = add;
if (add && get_server_version(server) == Server2_11)
ThisNick->halfop = ThisNick->hasvoice = 0;
}
break;
case 'n':
value = MODE_MSGS;
break;
case 'p':
value = MODE_PRIVATE;
break;
case 'q':
value = MODE_QUIET;
break;
case 'r':
value = MODE_REOP;
break;
case 's':
value = MODE_SECRET;
break;
case 't':
value = MODE_TOPIC;
break;
case 'v':
/**************************** PATCHED by Flier ******************************/
/*person = next_arg(rest, &rest);
ThisNick = (NickList *) list_lookup((List **) nicks, person, !USE_WILDCARDS, !REMOVE_FROM_LIST);
if (ThisNick)
ThisNick->hasvoice = add;
break;*/
if ((person = next_arg(rest, &rest)) && !my_stricmp(person, mynick))
{
if (add)
*chop |= CHAN_VOICE;
else
*chop &= ~CHAN_VOICE;
}
ThisNick = find_in_hash(chan, person);
if (!person) person = empty_string;
if (check && isserver) {
strmcat(servline, person, sizeof(servline));
strmcat(servline, " ", sizeof(servline));
}
if (check && chan->CompressModes && ThisNick) {
if ((add && !(ThisNick->hasvoice)) ||
(!add && ThisNick->hasvoice)) {
if (compadd != add) {
if (compmodelen < compmodemax) {
if (add) *compmodeadd ++= '+';
else *compmodeadd ++= '-';
compmodelen++;
}
compadd = add;
}
if (compmodelen < compmodemax) {
*compmodeadd ++= *mode_string;
compmodelen++;
}
strmcat(compline, person, sizeof(compline));
strmcat(compline, " ", sizeof(compline));
}
}
if (ThisNick) {
ThisNick->hasvoice = add;
if (ThisNick->frlist) privs = ThisNick->frlist->privs;
else privs = 0;
if (check && chan->FriendList && (privs & FLPROT) &&
(privs & FLVOICE) && HAS_OPS(*chop) && !isserver &&
!add && !isitme && my_stricmp(from, ThisNick->nick) &&
!CheckChannel(lastvoice, ThisNick->nick)) {
send_to_server("MODE %s +v %s", chan->channel,
ThisNick->nick);
if (*lastdeop) strmcat(lastvoice, ",", sizeof(lastvoice));
strmcat(lastvoice, ThisNick->nick, sizeof(lastvoice));
}
}
break;
/****************************************************************************/
case 'b':
case 'e':
/**************************** PATCHED by Flier ******************************/
/*(void) next_arg(rest, &rest);*/
if (!(person = next_arg(rest, &rest))) person = empty_string;
if (check) {
if (*mode_string == 'e') exception = 1;
else exception = 0;
if (tmpjoiner && !exception) {
if (add) tmpjoiner->plusb++;
else tmpjoiner->minusb++;
}
if (isserver) {
strmcat(servline, person, sizeof(servline));
strmcat(servline, " ", sizeof(servline));
if (!exception) {
if (add) chan->servplusb++;
else chan->servminusb++;
}
}
if (add) {
if (!exception) chan->plusb++;
if (userhost) snprintf(tmpbuf, sizeof(tmpbuf), "%s!%s", from, userhost);
else strmcpy(tmpbuf, from, sizeof(tmpbuf));
if (AddBan(person, chan->channel, server, tmpbuf, exception, timenow, chan)) {
if (chan->CompressModes) {
if (compadd != add) {
if (compmodelen < compmodemax) {
*compmodeadd ++= '+';
compmodelen++;
}
compadd = add;
}
if (compmodelen < compmodemax) {
*compmodeadd ++= *mode_string;
compmodelen++;
}
strmcat(compline, person, sizeof(compline));
strmcat(compline, " ", sizeof(compline));
}
}
if (!exception && !isitme && chan->FriendList) {
for (joiner = chan->nicks; joiner; joiner = joiner->next) {
if (joiner->frlist) privs = joiner->frlist->privs;
else privs = 0;
if ((privs & (FLPROT | FLGOD)) && (privs & FLUNBAN) &&
!(!(privs & FLGOD) && (isprot & FLGOD))) {
if (joiner->userhost)
snprintf(tmpbuf, sizeof(tmpbuf), "%s!%s", joiner->nick, joiner->userhost);
else strmcpy(tmpbuf, joiner->nick, sizeof(tmpbuf));
if (wild_match(person, tmpbuf)) {
if (*chop & CHAN_CHOP) {
if (!deopped && !(isprot & FLGOD) &&
!isserver && (privs & FLGOD)) {
count++;
strmcat(modebuf, "-o", sizeof(modebuf));
strmcat(tmpbufmode, " ", sizeof(tmpbufmode));
strmcat(tmpbufmode, from, sizeof(tmpbufmode));
deopped = 1;
}
if (count == max) {
send_to_server("MODE %s %s %s",
chan->channel,
modebuf,
tmpbufmode);
*tmpbufmode = '\0';
*modebuf = '\0';
count = 0;
}
if ((privs & FLGOD) ||
((privs & FLPROT) && !(isprot & FLGOD))) {
count++;
strmcat(modebuf, "-b", sizeof(tmpbuf));
strmcat(tmpbufmode, " ", sizeof(tmpbuf));
strmcat(tmpbufmode, person, sizeof(tmpbuf));
}
}
if (away_set || LogOn || (chan && chan->ChanLog)) {
snprintf(tmpbuf, sizeof(tmpbuf), "%cBan%c on mask %s on channel %s by %s",
bold, bold, person,
chan->channel, from);
if (!isserver) {
strmcat(tmpbuf, " (", sizeof(tmpbuf));
strmcat(tmpbuf, userhost, sizeof(tmpbuf));
strmcat(tmpbuf, ")", sizeof(tmpbuf));
}
if (away_set || LogOn) AwaySave(tmpbuf, SAVEPROT);
if (chan && chan->ChanLog) ChannelLogSave(tmpbuf, chan);
}
break;
}
}
}
if (!joiner) {
whowas = whowas_userlist_list;
if (!whowas) {
whowas = whowas_reg_list;
whowasdone = 1;
}
if (!whowas) whowasdone = 2;
while (whowasdone < 2) {
if (!whowas && !whowasdone) {
whowas = whowas_reg_list;
whowasdone = 1;
continue;
}
if (!whowas && whowasdone == 1) {
whowasdone = 2;
continue;
}
if (!my_stricmp(whowas->channel, chan->channel)) {
if (whowas->nicklist->frlist)
privs = whowas->nicklist->frlist->privs;
else privs = 0;
if (privs & (FLGOD | FLPROT) && (privs & FLUNBAN) &&
!(!(privs & FLGOD) && (isprot & FLGOD))) {
if (whowas->nicklist->userhost)
snprintf(tmpbuf, sizeof(tmpbuf), "%s!%s",
whowas->nicklist->nick,
whowas->nicklist->userhost);
else strmcpy(tmpbuf, whowas->nicklist->nick, sizeof(tmpbuf));
if (wild_match(person, tmpbuf)) {
if (*chop & CHAN_CHOP) {
count++;
strmcat(modebuf, "-b", sizeof(modebuf));
strmcat(tmpbufmode, " ", sizeof(tmpbufmode));
strmcat(tmpbufmode, person, sizeof(tmpbufmode));
if (count == max) {
send_to_server("MODE %s %s %s",
chan->channel,
modebuf,
tmpbufmode);
*tmpbufmode = '\0';
*modebuf = '\0';
count = 0;
}
if (!deopped && !isprot && !isserver &&
(privs & FLGOD)) {
count++;
strmcat(modebuf, "-o", sizeof(modebuf));
strmcat(tmpbufmode, " ", sizeof(tmpbufmode));
strmcat(tmpbufmode, from, sizeof(tmpbufmode));
}
deopped = 1;
}
if (away_set || LogOn || (chan && chan->ChanLog)) {
snprintf(tmpbuf, sizeof(tmpbuf),
"%cBan%c on mask %s on channel %s by %s",
bold, bold, person,
chan->channel, from);
if (!isserver) {
strmcat(tmpbuf, " (", sizeof(tmpbuf));
strmcat(tmpbuf, userhost, sizeof(tmpbuf));
strmcat(tmpbuf, ")", sizeof(tmpbuf));
}
if (away_set || LogOn) AwaySave(tmpbuf, SAVEPROT);
if (chan && chan->ChanLog)
ChannelLogSave(tmpbuf, chan);
}
break;
}
}
}
whowas = whowas->next;
}
}
}
}
else {
if (!exception) chan->minusb++;
minusban = 1;
if (RemoveBan(person, exception, chan)) {
if (chan->CompressModes) {
if (compadd != add) {
if (compmodelen < compmodemax) {
*compmodeadd ++= '-';
compmodelen++;
}
compadd = add;
}
if (compmodelen < compmodemax) {
*compmodeadd ++= *mode_string;
compmodelen++;
}
strmcat(compline, person, sizeof(compline));
strmcat(compline, " ", sizeof(compline));
}
}
}
}
/****************************************************************************/
break;
/**************************** PATCHED by Flier ******************************/
/*case 'e':*/
/* we handle e properly together with b above */
/****************************************************************************/
case 'I':
case 'O':
case 'R': /* this is a weird special case */
/**************************** Patched by Flier ******************************/
/*(void) next_arg(rest, &rest);*/
arg = next_arg(rest, &rest);
if (arg && check && chan->CompressModes) {
strmcat(compline, arg, sizeof(compline));
strmcat(compline, " ", sizeof(compline));
}
/****************************************************************************/
break;
/**************************** PATCHED by Flier ******************************/
/*case 'R':
value = MODE_REGONLY;
break;*/
case 'S':
value = MODE_SSLONLY;
break;
/****************************************************************************/
}
if (add)
*mode |= value;
else
*mode &= ~value;
/**************************** PATCHED by Flier ******************************/
if (check && count == max) {
if (HAS_OPS(*chop)) send_to_server("MODE %s %s %s", chan->channel,
modebuf, tmpbufmode);
*tmpbufmode = '\0';
*modebuf = '\0';
count = 0;
}
/****************************************************************************/
}
/**************************** PATCHED by Flier ******************************/
if (*nethackbuf && nethacks) strmcpy(nethacks, nethackbuf, sizeof(nethackbuf));
if (tmpjoiner && tmpjoiner->frlist) privs = tmpjoiner->frlist->privs;
else privs = 0;
if (chan->FriendList && chan->MDopWatch && tmpjoiner && !isitme &&
!(privs & (FLGOD | FLPROT))) {
if (tmpjoiner->curo >= DeopSensor && tmpjoiner->curo < DeopSensor * 2) {
if (!(tmpjoiner->deopp)) {
if (!deopped && !isserver && (*chop & CHAN_CHOP)) {
count++;
strmcat(modebuf, "-o", sizeof(modebuf));
strmcat(tmpbufmode, " ", sizeof(tmpbufmode));
strmcat(tmpbufmode, from, sizeof(tmpbufmode));
}
deopped = 1;
#ifdef WANTANSI
snprintf(tmpbuf, sizeof(tmpbuf), "%sMass deop%s detected on %s%s%s by %s%s%s",
CmdsColors[COLWARNING].color1, Colors[COLOFF],
CmdsColors[COLWARNING].color4, chan->channel, Colors[COLOFF],
CmdsColors[COLWARNING].color2, from, Colors[COLOFF]);
#else
snprintf(tmpbuf, sizeof(tmpbuf),"%cMass deop%c detected on %s by %s",
bold, bold, chan->channel, from);
#endif
say("%s", tmpbuf);
if (away_set || LogOn || (chan && chan->ChanLog)) {
if (!isserver) {
strmcat(tmpbuf, " (", sizeof(tmpbuf));
strmcat(tmpbuf, userhost, sizeof(tmpbuf));
strmcat(tmpbuf, ")", sizeof(tmpbuf));
}
if (away_set || LogOn) AwaySave(tmpbuf, SAVEMASS);
if (chan && chan->ChanLog) ChannelLogSave(tmpbuf, chan);
}
}
tmpjoiner->deopp = 1;
}
else if (tmpjoiner->curo >= DeopSensor * 2) {
if (tmpjoiner->deopp < 2) {
if (!deopped && !isserver && chan->KickOnFlood && (*chop & CHAN_CHOP))
send_to_server("KICK %s %s :Deop flood detected", chan->channel, from);
deopped = 1;
#ifdef WANTANSI
snprintf(tmpbuf, sizeof(tmpbuf), "%sDeop flood%s detected on %s%s%s by %s%s%s",
CmdsColors[COLWARNING].color1, Colors[COLOFF],
CmdsColors[COLWARNING].color4, chan->channel, Colors[COLOFF],
CmdsColors[COLWARNING].color2, from, Colors[COLOFF]);
#else
snprintf(tmpbuf, sizeof(tmpbuf),"%cDeop flood%c detected on %s by %s",
bold, bold, chan->channel, from);
#endif
say("%s", tmpbuf);
if (away_set || LogOn || (chan && chan->ChanLog)) {
snprintf(tmpbuf, sizeof(tmpbuf), "%cDeop flood%c detected on %s by %s",
bold, bold, chan->channel, from);
if (!isserver) {
strmcat(tmpbuf, " (", sizeof(tmpbuf));
strmcat(tmpbuf, userhost, sizeof(tmpbuf));
strmcat(tmpbuf, ")", sizeof(tmpbuf));
}
if (away_set || LogOn) AwaySave(tmpbuf, SAVEMASS);
if (chan && chan->ChanLog) ChannelLogSave(tmpbuf, chan);
}
}
tmpjoiner->deopp = 2;
}
}
if (check) {
if (HAS_OPS(*chop) && count)
send_to_server("MODE %s %s %s", chan->channel, modebuf, tmpbufmode);
if ((chan->status & CHAN_CHOP) && chan->NHProt && *nhdeop)
send_to_server("MODE %s %s", chan->channel, nhdeop);
*servmodeadd = '\0';
if (*servmodes) {
if (*servline) {
strmcat(servmodes, " ", sizeof(servline));
strmcat(servmodes, servline, sizeof(servline));
}
if (servmodes[strlen(servmodes) - 1] == ' ')
servmodes[strlen(servmodes) - 1] = '\0';
}
if (!chan->gotbans || !chan->gotwho) gotops = 0;
if (!isitme && minusban && HAS_OPS(*chop) && chan->gotbans && chan->gotwho && !gotops && chan->BKList)
CheckPermBans(chan);
if (!isitme && gotops)
HandleGotOps(mynick, chan);
if (chan->CompressModes) {
*compmodeadd = '\0';
if (*compmode) snprintf(origmode, modelen, "%s %s", compmode, compline);
else *origmode = '\0';
if (*origmode && origmode[strlen(origmode) - 1] == ' ')
origmode[strlen(origmode) - 1] = '\0';
}
else strmcpy(origmode, tmporigmode, modelen);
}
/****************************************************************************/
if (limit_set)
return (atoi(limit));
else if (limit_reset)
return(0);
else
return(-1);
}
/*
* get_channel_mode: returns the current mode string for the given channel
*/
char *
get_channel_mode(channel, server)
char *channel;
int server;
{
ChannelList *tmp;
if ((tmp = lookup_channel(channel, server, CHAN_NOUNLINK)) && (tmp->status & CHAN_MODE))
return recreate_mode(tmp);
return empty_string;
}
/*
* update_channel_mode: This will modify the mode for the given channel
* according the the new mode given.
*/
void
/**************************** PATCHED by Flier ******************************/
/*update_channel_mode(channel, server, mode)
char *channel;
int server;
char *mode;*/
update_channel_mode(channel,server,mode,modelen,from,userhost,nethacks,servmodes,tmpchan)
char *channel;
int server;
char *mode;
int modelen;
char *from;
char *userhost;
char *nethacks;
char *servmodes;
ChannelList *tmpchan;
/****************************************************************************/
{
ChannelList *tmp;
int limit;
/**************************** PATCHED by Flier ******************************/
if (tmpchan) tmp=tmpchan;
else tmp=lookup_channel(channel, server, CHAN_NOUNLINK);
/*if ((tmp = lookup_channel(channel, server, CHAN_NOUNLINK)) &&*/
if (tmp &&
/*(limit = decifer_mode(mode, &(tmp->mode), &(tmp->chop), &(tmp->nicks), &(tmp->key))) != -1)*/
(limit = decifer_mode(mode, modelen, &(tmp->mode), &(tmp->status), &(tmp->nicks),
&(tmp->key), tmp, from, userhost, nethacks, servmodes))!=-1)
/****************************************************************************/
tmp->limit = limit;
}
/*
* 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(channel, mode, server_index)
char *channel;
int mode;
int server_index;
{
ChannelList *tmp;
if ((tmp = lookup_channel(channel, server_index, CHAN_NOUNLINK)))
return (tmp->mode & mode);
return 0;
}
static void
free_channel(channel)
ChannelList **channel;
{
/**************************** PATCHED by Flier ******************************/
/*clear_channel(*channel);
new_free(&(*channel)->channel);
new_free(&(*channel)->key);
new_free(&(*channel)->s_mode);
new_free(&(*channel));*/
NickList *nick,*tmpnick;
ChannelLogReport("ended", *channel);
(*channel)->mode=0;
(*channel)->limit=0;
new_free(&((*channel)->key));
new_free(&((*channel)->s_mode));
new_free(&((*channel)->topicstr));
new_free(&((*channel)->topicwho));
ClearBans((*channel));
for (nick=(*channel)->nicks;nick;) {
tmpnick=nick;
nick=nick->next;
add_to_whowas_buffer(tmpnick,(*channel)->channel);
}
(*channel)->nicks=(NickList *) 0;
if (!(add_to_whowas_chan_buffer((*channel)))) {
clear_channel(*channel);
new_free(&(*channel)->channel);
new_free(&(*channel));
}
/****************************************************************************/
}
/*
* remove_channel: removes the named channel from the
* server_list[server].chan_list. If the channel is not on the
* server_list[server].chan_list, nothing happens. If the channel was
* the current channel, this will select the top of the
* server_list[server].chan_list to be the current_channel, or 0 if the
* list is empty.
*/
void
remove_channel(channel, server)
char *channel;
int server;
{
ChannelList *tmp;
if (channel)
{
int refnum = -1;
if ((tmp = lookup_channel(channel, server, CHAN_NOUNLINK)))
{
tmp = lookup_channel(channel, server, CHAN_UNLINK);
if (tmp->window)
refnum = tmp->window->refnum;
free_channel(&tmp);
}
(void)is_current_channel(channel, server, refnum);
}
else
{
ChannelList *next;
for (tmp = server_list[server].chan_list; tmp; tmp = next)
{
next = tmp->next;
free_channel(&tmp);
}
server_list[server].chan_list = (ChannelList *) 0;
}
update_all_windows();
}
/**************************** PATCHED by Flier ******************************/
/*
* purge given channel from memory, for use on numeric 405
*/
void
PurgeChannel(channel,server)
char *channel;
int server;
{
ChannelList *tmp;
if ((tmp=lookup_channel(channel,server,CHAN_UNLINK))) {
new_free(&(tmp->key));
new_free(&(tmp->s_mode));
new_free(&(tmp->topicstr));
new_free(&(tmp->topicwho));
new_free(&(tmp->channel));
/* clear_channel removes bans */
clear_channel(tmp);
new_free(&tmp);
}
}
/* removes given nick's entry from hash table */
void remove_nick_from_hash(chan,tmp)
ChannelList *chan;
NickList *tmp;
{
int i=HashFunc(tmp->nick);
struct hashstr *tmphash;
struct hashstr *prevhash=NULL;
if (!chan || !tmp || !(tmp->nick)) return;
for (tmphash=chan->nickshash[i];tmphash;) {
if (tmphash->nick==tmp) break;
prevhash=tmphash;
tmphash=tmphash->next;
}
if (prevhash) prevhash->next=tmphash->next;
else if (tmphash) chan->nickshash[i]=tmphash->next;
new_free(&tmphash);
}
/****************************************************************************/
/*
* 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
remove_from_channel(channel, nick, server)
char *channel;
char *nick;
int server;
{
ChannelList *chan;
NickList *tmp;
if (channel)
{
if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)))
{
if ((tmp = (NickList *) list_lookup((List **) &(chan->nicks), nick, !USE_WILDCARDS, REMOVE_FROM_LIST)))
{
/**************************** PATCHED by Flier ******************************/
/*new_free(&(tmp->nick));
new_free(&tmp);*/
remove_nick_from_hash(chan,tmp);
add_to_whowas_buffer(tmp,channel);
/****************************************************************************/
}
}
}
else
{
for (chan = server_list[server].chan_list; chan; chan = chan->next)
{
if ((tmp = (NickList *) list_lookup((List **) &(chan->nicks), nick, !USE_WILDCARDS, REMOVE_FROM_LIST)))
{
/**************************** PATCHED by Flier ******************************/
/*new_free(&(tmp->nick));
new_free(&tmp);*/
remove_nick_from_hash(chan,tmp);
add_to_whowas_buffer(tmp,chan->channel);
/****************************************************************************/
}
}
}
/**************************** PATCHED by Flier ******************************/
update_all_status();
/****************************************************************************/
}
/*
* 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
rename_nick(old_nick, new_nick, server)
char *old_nick,
*new_nick;
int server;
{
ChannelList *chan;
NickList *tmp;
/**************************** PATCHED by Flier ******************************/
char tmpbuf[mybufsize/8];
/****************************************************************************/
for (chan = server_list[server].chan_list; chan; chan = chan->next)
{
if ((chan->server == server) != 0)
{
/**************************** PATCHED by Flier ******************************/
/*if ((tmp = (NickList *) list_lookup((List **) &chan->nicks, old_nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)))*/
#ifdef SORTED_NICKS
if ((tmp=(NickList *) list_lookup((List **) &chan->nicks,
old_nick,!USE_WILDCARDS,REMOVE_FROM_LIST)) != NULL)
#else
if ((tmp=find_in_hash(chan,old_nick)))
#endif
/****************************************************************************/
{
/**************************** PATCHED by Flier ******************************/
remove_nick_from_hash(chan,tmp);
/****************************************************************************/
new_free(&tmp->nick);
malloc_strcpy(&tmp->nick, new_nick);
/**************************** PATCHED by Flier ******************************/
#ifdef SORTED_NICKS
add_to_list_ext((List **) &(chan->nicks), (List *) tmp,
SortedCmp);
#endif
add_nick_to_hash(chan,tmp);
if (tmp->userhost) {
snprintf(tmpbuf,sizeof(tmpbuf),"%s!%s",tmp->nick,tmp->userhost);
tmp->frlist=(struct friends *) FindMatch(tmpbuf,chan->channel);
}
/****************************************************************************/
}
}
}
}
/*
* 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
is_on_channel(channel, server, nick)
char *channel;
int server;
char *nick;
{
ChannelList *chan;
chan = lookup_channel(channel, server, CHAN_NOUNLINK);
if (chan && (chan->connected == CHAN_JOINED)
/* channel may be "surviving" from a server disconnect/reconnect,
make sure it's connected -Sol */
/**************************** PATCHED by Flier ******************************/
/*&& list_lookup((List **) &(chan->nicks), nick, !USE_WILDCARDS, !REMOVE_FROM_LIST))*/
&& find_in_hash(chan,nick))
/****************************************************************************/
return 1;
return 0;
}
int
is_chanop(channel, nick)
char *channel;
char *nick;
{
ChannelList *chan;
NickList *Nick;
if ((chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)) &&
(chan->connected == CHAN_JOINED) &&
/* channel may be "surviving" from a disconnect/connect
check here too -Sol */
/**************************** PATCHED by Flier ******************************/
/*(Nick = (NickList *) list_lookup((List **) &(chan->nicks),
nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)) && Nick->chanop)*/
(Nick=find_in_hash(chan,nick)) && (Nick->chanop || Nick->halfop))
/****************************************************************************/
return 1;
return 0;
}
int
has_voice(channel, nick, server)
char *channel;
char *nick;
int server;
{
ChannelList *chan;
NickList *Nick;
if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)) &&
(chan->connected == CHAN_JOINED) &&
/* channel may be "surviving" from a disconnect/connect
check here too -Sol */
/**************************** PATCHED by Flier ******************************/
/*(Nick = (NickList *) list_lookup((List **) &(chan->nicks),
nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)) && (Nick->chanop || Nick->hasvoice))*/
(Nick = find_in_hash(chan, nick)) && Nick->hasvoice)
/****************************************************************************/
return 1;
return 0;
}
static void
show_channel(chan)
ChannelList *chan;
{
NickList *tmp;
int buffer_len,
len;
char *nicks = (char *) 0;
char *s;
char buffer[BIG_BUFFER_SIZE+1];
s = recreate_mode(chan);
*buffer = (char) 0;
buffer_len = 0;
for (tmp = chan->nicks; tmp; tmp = tmp->next)
{
len = strlen(tmp->nick);
if (buffer_len + len >= (BIG_BUFFER_SIZE / 2))
{
malloc_strcpy(&nicks, buffer);
say("\t%s +%s (%s): %s", chan->channel, s, get_server_name(chan->server), nicks);
*buffer = (char) 0;
buffer_len = 0;
}
strmcat(buffer, tmp->nick, BIG_BUFFER_SIZE);
strmcat(buffer, " ", BIG_BUFFER_SIZE);
buffer_len += len + 1;
}
malloc_strcpy(&nicks, buffer);
say("\t%s +%s (%s): %s", chan->channel, s, get_server_name(chan->server), nicks);
new_free(&nicks);
}
/* list_channels: displays your current channel and your channel list */
void
list_channels()
{
ChannelList *tmp;
int server,
no = 1;
int first;
if (connected_to_server < 1)
{
say("You are not connected to a server, use /SERVER to connect.");
return;
}
if (get_channel_by_refnum(0))
say("Current channel %s", get_channel_by_refnum(0));
else
say("No current channel for this window");
first = 1;
for (tmp = server_list[get_window_server(0)].chan_list; tmp; tmp = tmp->next)
{
if (tmp->connected != CHAN_JOINED)
continue;
if (first)
say("You are on the following channels:");
show_channel(tmp);
first = 0;
no = 0;
}
if (connected_to_server > 1)
{
for (server = 0; server < number_of_servers; server++)
{
if (server == get_window_server(0))
continue;
first = 1;
for (tmp = server_list[server].chan_list; tmp; tmp = tmp->next)
{
if (tmp->connected != CHAN_JOINED)
continue;
if (first)
say("Other servers:");
show_channel(tmp);
first = 0;
no = 0;
}
}
}
if (no)
say("You are not on any channels");
}
void
switch_channels(key, ptr)
u_int key;
char * ptr;
{
ChannelList * tmp;
char * s;
/**************************** PATCHED by Flier ******************************/
if (!is_server_valid(from_server))
return;
/****************************************************************************/
if (server_list[from_server].chan_list)
{
if (get_channel_by_refnum(0))
{
if ((tmp = lookup_channel(get_channel_by_refnum(0), from_server, CHAN_NOUNLINK)))
{
for (tmp = tmp->next; tmp; tmp = tmp->next)
{
s = tmp->channel;
if (!is_current_channel(s, from_server, 0) && !(is_bound(s, from_server) && curr_scr_win != tmp->window))
{
set_channel_by_refnum(0, s);
update_all_windows();
/**************************** PATCHED by Flier ******************************/
tabnickcompl=NULL;
/****************************************************************************/
return;
}
}
}
}
for (tmp = server_list[from_server].chan_list; tmp; tmp = tmp->next)
{
s = tmp->channel;
if (!is_current_channel(s, from_server, 0) && !(is_bound(s, from_server) && curr_scr_win != tmp->window))
{
set_channel_by_refnum(0, s);
update_all_windows();
/**************************** PATCHED by Flier ******************************/
tabnickcompl=NULL;
/****************************************************************************/
return;
}
}
}
}
void
change_server_channels(old, new)
int old,
new;
{
ChannelList *tmp;
if (new == old)
return;
if (old > -1)
{
for (tmp = server_list[old].chan_list; tmp ;tmp = tmp->next)
tmp->server = new;
server_list[new].chan_list = server_list[old].chan_list;
}
else
server_list[new].chan_list = (ChannelList *) 0;
}
void
clear_channel_list(server)
int server;
{
ChannelList *tmp,
*next;
Window *ptr;
int flag = 1;
while ((ptr = traverse_all_windows(&flag)))
if (ptr->server == server && ptr->current_channel)
new_free(&ptr->current_channel);
for (tmp = server_list[server].chan_list; tmp; tmp = next)
{
next = tmp->next;
/**************************** PATCHED by Flier ******************************/
/*free_channel(&tmp);*/
remove_channel(tmp->channel,tmp->server);
/****************************************************************************/
}
server_list[server].chan_list = (ChannelList *) 0;
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(server)
int server;
{
ChannelList *tmp = (ChannelList *) 0;
char *mode, *chan;
/**************************** PATCHED by Flier ******************************/
ChannelList *next, *tmpchan, *newchan;
/****************************************************************************/
/**************************** PATCHED by Flier ******************************/
/*for (tmp = server_list[server].chan_list; tmp; tmp = tmp->next)*/
for (tmp = server_list[server].chan_list; tmp; tmp = next)
/****************************************************************************/
{
/**************************** PATCHED by Flier ******************************/
next = tmp->next;
/****************************************************************************/
mode = recreate_mode(tmp);
chan = tmp->channel;
/**************************** PATCHED by Flier ******************************/
if (RateLimitJoin(server) && tmp != server_list[server].chan_list) {
newchan = (ChannelList *) new_malloc(sizeof(ChannelList));
newchan->channel = (char *) 0;
newchan->key = (char *) 0;
newchan->s_mode = (char *) 0;
newchan->topicstr = (char *) 0;
malloc_strcpy(&newchan->channel, tmp->channel);
malloc_strcpy(&newchan->key, tmp->key);
malloc_strcpy(&newchan->s_mode, empty_string);
malloc_strcpy(&newchan->topicstr, "JOIN");
newchan->status = 0;
newchan->connected = 0;
newchan->next = NULL;
for (tmpchan = server_list[from_server].ChanPendingList;
tmpchan && tmpchan->next; ) {
tmpchan = tmpchan->next;
}
if (tmpchan) tmpchan->next = newchan;
else server_list[from_server].ChanPendingList = newchan;
}
else {
/****************************************************************************/
if (get_server_version(server) >= Server2_8)
send_to_server("JOIN %s%s%s", tmp->channel, tmp->key ? " " : "", tmp->key ? tmp->key : "");
else
send_to_server("JOIN %s%s%s", tmp->channel, mode ? " " : "", mode ? mode : "");
tmp->connected = CHAN_JOINING;
/**************************** PATCHED by Flier ******************************/
}
/****************************************************************************/
}
}
char *
what_channel(nick, server)
char *nick;
int server;
{
ChannelList *tmp;
if (curr_scr_win->current_channel && is_on_channel(curr_scr_win->current_channel, curr_scr_win->server, nick))
return curr_scr_win->current_channel;
for (tmp = server_list[from_server].chan_list; tmp; tmp = tmp->next)
/**************************** PATCHED by Flier ******************************/
/*if (list_lookup((List **) &(tmp->nicks), nick, !USE_WILDCARDS, !REMOVE_FROM_LIST))*/
if (find_in_hash(tmp,nick))
/****************************************************************************/
return tmp->channel;
return (char *) 0;
}
char *
walk_channels(nick, init, server)
int init;
char *nick;
int server;
{
static ChannelList *tmp = (ChannelList *) 0;
if (init)
tmp = server_list[server].chan_list;
else if (tmp)
tmp = tmp->next;
for (;tmp ; tmp = tmp->next)
/**************************** PATCHED by Flier ******************************/
/*if ((tmp->server == from_server) && (list_lookup((List **) &(tmp->nicks), nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)))*/
if ((tmp->server == from_server) && (find_in_hash(tmp,nick)))
/****************************************************************************/
return (tmp->channel);
return (char *) 0;
}
int
get_channel_oper(channel, server)
char *channel;
int server;
{
ChannelList *chan;
if ((chan = lookup_channel(channel, server, CHAN_NOUNLINK)))
return (chan->status & CHAN_CHOP);
else
return 1;
}
extern void
set_channel_window(window, channel, server)
Window *window;
char *channel;
int server;
{
ChannelList *tmp;
if (!channel)
return;
for (tmp = server_list[server].chan_list; tmp; tmp = tmp->next)
if (!my_stricmp(channel, tmp->channel))
{
tmp->window = window;
return;
}
}
extern char *
create_channel_list(window)
Window *window;
{
ChannelList *tmp;
char *value = (char *) 0;
char buffer[BIG_BUFFER_SIZE+1];
*buffer = '\0';
for (tmp = server_list[window->server].chan_list; tmp; tmp = tmp->next)
{
/**************************** Patched by Flier ******************************/
/*strcat(buffer, tmp->channel);
strcat(buffer, " ");*/
strmcat(buffer, tmp->channel, sizeof(buffer));
strmcat(buffer, " ", sizeof(buffer));
/****************************************************************************/
}
malloc_strcpy(&value, buffer);
return value;
}
extern void
channel_server_delete(server)
int server;
{
ChannelList *tmp;
int i;
for (i = server + 1; i < number_of_servers; i++)
for (tmp = server_list[i].chan_list ; tmp; tmp = tmp->next)
if (tmp->server >= server)
tmp->server--;
}
extern int
chan_is_connected(channel, server)
char * channel;
int server;
{
ChannelList * cp = lookup_channel(channel, server, CHAN_NOUNLINK);
if (!cp)
return 0;
return (cp->connected == CHAN_JOINED);
}
void
mark_not_connected(server)
int server;
{
ChannelList *tmp;
for (tmp = server_list[server].chan_list; tmp; tmp = tmp->next)
{
tmp->status = 0;
tmp->connected = CHAN_LIMBO;
/**************************** Patched by Flier ******************************/
if (tmp->gotwho < 2) tmp->gotwho = 0;
/****************************************************************************/
}
}
syntax highlighted by Code2HTML, v. 0.9.1