971 lines
21 KiB
C
971 lines
21 KiB
C
/* @(#)$Id: modes.c,v 1.10 1999/04/04 17:00:11 seks Exp $ */
|
||
|
||
/* Undernet Channel Service (X)
|
||
* Copyright (C) 1995-2002 Robin Thellend
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, write to the Free Software
|
||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
*
|
||
* The author can be contact by email at <csfeedback@robin.pfft.net>
|
||
*
|
||
* Please note that this software is unsupported and mostly
|
||
* obsolete. It was replaced by GNUworld/CMaster. See
|
||
* http://gnuworld.sourceforge.net/ for more information.
|
||
*/
|
||
|
||
#include "h.h"
|
||
|
||
static void AddFlag(char *, char, char *);
|
||
static void RemFlag(char *, char);
|
||
|
||
void setchanmode(char *line)
|
||
{
|
||
register char *mode;
|
||
register achannel *chan;
|
||
|
||
if ((mode = strchr(line, ' ')) != NULL)
|
||
*(mode++) = 0;
|
||
chan = ToChannel(line);
|
||
if (!chan)
|
||
return;
|
||
strcpy(chan->mode, mode + 1); /* why +1 ???? coz I don't want the + */
|
||
}
|
||
|
||
void AddFlag(char *string, char flag, char *arg)
|
||
{
|
||
char newmode[15];
|
||
char newarg[200];
|
||
|
||
if (strchr(string, flag))
|
||
RemFlag(string, flag);
|
||
|
||
GetWord(0, string, newmode);
|
||
*(newmode + strlen(newmode) + 1) = 0;
|
||
*(newmode + strlen(newmode)) = flag;
|
||
strcpy(newarg, ToWord(1, string));
|
||
if (arg)
|
||
{
|
||
strcat(newarg, arg);
|
||
strcat(newarg, " ");
|
||
}
|
||
|
||
sprintf(string, "%s %s", newmode, newarg);
|
||
}
|
||
|
||
void RemFlag(char *string, char flag)
|
||
{
|
||
char newmode[15];
|
||
char newarg[200];
|
||
register char *ptr;
|
||
register char *curr = newmode;
|
||
register int count = 0;
|
||
|
||
GetWord(0, string, newmode);
|
||
strcpy(newarg, ToWord(1, string));
|
||
|
||
while (*curr)
|
||
{
|
||
ptr = strchr("lk", *curr);
|
||
if (*curr == flag)
|
||
{
|
||
strcpy(curr, curr + 1);
|
||
if (ptr)
|
||
strcpy(ToWord(count, newarg), ToWord(count + 1, newarg));
|
||
}
|
||
else
|
||
{
|
||
if (ptr)
|
||
count++;
|
||
curr++;
|
||
}
|
||
}
|
||
sprintf(string, "%s %s", newmode, newarg);
|
||
}
|
||
|
||
int IsSet(char *channel, char flag, char *param)
|
||
{
|
||
register achannel *chan;
|
||
register char *setmode;
|
||
char setflags[20];
|
||
char setparam[80];
|
||
register int out;
|
||
register int i, j;
|
||
|
||
chan = ToChannel(channel);
|
||
if (chan == NULL)
|
||
return 0;
|
||
|
||
setmode = chan->mode;
|
||
GetWord(0, setmode, setflags);
|
||
|
||
j = 0;
|
||
for (i = 0; setflags[i] != '\0' && setflags[i] != flag; i++)
|
||
{
|
||
if (setflags[i] == 'l' || setflags[i] == 'k')
|
||
j++;
|
||
}
|
||
|
||
if (setflags[i] != '\0')
|
||
{
|
||
if (flag == 'l' || flag == 'k')
|
||
{
|
||
GetWord(j + 1, setmode, setparam);
|
||
if (!strcmp(setparam, param))
|
||
out = 1;
|
||
else
|
||
out = 0;
|
||
}
|
||
else
|
||
{
|
||
out = 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
out = 0;
|
||
}
|
||
#ifdef DEBUG
|
||
printf("IsSet(): +%c %s on %s (%d)\n", flag, param, channel, out);
|
||
#endif
|
||
return (out);
|
||
}
|
||
|
||
void bounce(char *channel, char *change, time_t TS)
|
||
{
|
||
char buffer[200];
|
||
char arg[200];
|
||
register char sign = '+';
|
||
register auser *user;
|
||
register achannel *chan;
|
||
register int pos = 1;
|
||
register int i;
|
||
|
||
chan = ToChannel(channel);
|
||
|
||
for (i = 0; change[i] != '\0' && change[i] != ' '; i++)
|
||
{
|
||
if (change[i] == '+')
|
||
sign = '+';
|
||
else if (change[i] == '-')
|
||
sign = '-';
|
||
else if (change[i] == 'o')
|
||
{
|
||
GetWord(pos++, change, arg);
|
||
user = ToUser(channel, arg);
|
||
if (user == NULL)
|
||
continue;
|
||
if (sign == '+')
|
||
{
|
||
if (!user->chanop)
|
||
{
|
||
changemode(channel, "-o", arg, 1);
|
||
user->chanop = 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (user->chanop)
|
||
{
|
||
/*
|
||
changemode(channel,"+o",arg,1);
|
||
user->chanop=1;
|
||
*/
|
||
/* don't bounce -o */
|
||
user->chanop = 0;
|
||
}
|
||
}
|
||
}
|
||
else if (change[i] == 'v')
|
||
{
|
||
GetWord(pos++, change, arg);
|
||
if (sign == '+')
|
||
changemode(channel, "-v", arg, 1);
|
||
else
|
||
changemode(channel, "+v", arg, 1);
|
||
}
|
||
else if (change[i] == 'k')
|
||
{
|
||
GetWord(pos++, change, arg);
|
||
if (sign == '+')
|
||
{
|
||
if (!IsSet(channel, 'k', arg))
|
||
changemode(channel, "-k", arg, 1);
|
||
}
|
||
else
|
||
{
|
||
if (IsSet(channel, 'k', arg))
|
||
changemode(channel, "+k", arg, 1);
|
||
}
|
||
}
|
||
else if (change[i] == 'l')
|
||
{
|
||
pos++;
|
||
if (sign == '+' && !IsSet(channel, 'l', arg))
|
||
changemode(channel, "-l", "", 1);
|
||
|
||
}
|
||
else if ((IsSet(channel, change[i], "") && sign == '-') ||
|
||
(!IsSet(channel, change[i], "") && sign == '+'))
|
||
{
|
||
sprintf(buffer, "%c%c",
|
||
(sign == '+') ? '-' : '+',
|
||
change[i]);
|
||
changemode(channel, buffer, "", 1);
|
||
}
|
||
}
|
||
AddEvent(EVENT_FLUSHMODEBUFF, now + MODE_DELAY, channel);
|
||
}
|
||
|
||
|
||
void ModeChange(char *source, char *channel, char *change)
|
||
{
|
||
register char sign = '+';
|
||
char arg[200];
|
||
register char *ptr;
|
||
register achannel *chan;
|
||
register aluser *u;
|
||
register int count = 1;
|
||
int desync = 0;
|
||
|
||
#ifdef DEBUG
|
||
printf("ModeChange(%s, %s, %s)\n", source, channel, change);
|
||
#endif
|
||
chan = ToChannel(channel);
|
||
/* if chan == NULL at this point.. we're dealing with a
|
||
* user mode change
|
||
*/
|
||
if (chan != NULL)
|
||
chan->lastact = now;
|
||
|
||
u = ToLuser(source);
|
||
if (chan == NULL && u == NULL)
|
||
{
|
||
return; /* probably a lost MODE */
|
||
}
|
||
if (u == NULL)
|
||
{
|
||
/* This is a mode change from a server.. if it is not
|
||
* a +b, then the last argument is a TS
|
||
*/
|
||
for (ptr = change; *ptr != 'b' && *ptr != ' '; ptr++);
|
||
if (*ptr != 'b' && strcasecmp(UWORLD_SERVER, source)
|
||
#ifdef UWORLD2
|
||
&& strcasecmp(UWORLD2_SERVER, source)
|
||
#endif
|
||
#ifdef FAKE_UWORLD
|
||
&& strcasecmp(UFAKE_SERVER, source)
|
||
#endif
|
||
)
|
||
{
|
||
ptr = change + strlen(change);
|
||
while (*ptr != ' ')
|
||
ptr--;
|
||
*(ptr++) = '\0';
|
||
if (atol(ptr) > chan->TS && atol(ptr) != 0 && chan->on)
|
||
{
|
||
log(source);
|
||
log(channel);
|
||
log(change);
|
||
log(ptr);
|
||
bounce(channel, change, chan->TS);
|
||
return;
|
||
}
|
||
if (atol(ptr) != 0)
|
||
chan->TS = atol(ptr);
|
||
}
|
||
}
|
||
|
||
while (*change && *change != ' ')
|
||
{
|
||
if (*change == '+')
|
||
{
|
||
sign = '+';
|
||
}
|
||
else if (*change == '-')
|
||
{
|
||
sign = '-';
|
||
}
|
||
else
|
||
{
|
||
if (sign == '+')
|
||
{
|
||
if (chan != NULL)
|
||
{
|
||
ptr = strchr("blkov", *change);
|
||
if (ptr)
|
||
{
|
||
GetWord(count, change, arg);
|
||
if (strchr("lk", *change) && *arg)
|
||
AddFlag(chan->mode, *change, arg);
|
||
count++;
|
||
}
|
||
else
|
||
{
|
||
if (strchr("imntps", *change))
|
||
AddFlag(chan->mode, *change, NULL);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* user mode change (+) */
|
||
if (*change == 'o')
|
||
{
|
||
u->mode |= LFL_ISOPER;
|
||
#ifdef DEBUG
|
||
printf("%s is now IRCOP\n", source);
|
||
#endif
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (chan != NULL)
|
||
{
|
||
ptr = strchr("bkov", *change);
|
||
if (strchr("ilkmntps", *change))
|
||
RemFlag(chan->mode, *change);
|
||
if (ptr)
|
||
{
|
||
GetWord(count, change, arg);
|
||
count++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* user mode change (-) */
|
||
if (*change == 'o')
|
||
{
|
||
u->mode &= ~LFL_ISOPER;
|
||
#ifdef DEBUG
|
||
printf("%s is no longer IRCOP\n", source);
|
||
#endif
|
||
}
|
||
}
|
||
}
|
||
|
||
/** other tests should go here **/
|
||
|
||
if (chan != NULL)
|
||
{
|
||
if (*change == 'o')
|
||
{
|
||
if (sign == '+')
|
||
onop(source, channel, arg);
|
||
else
|
||
ondeop(source, channel, arg, &desync);
|
||
}
|
||
else if (*change == 'b')
|
||
{
|
||
if (sign == '+')
|
||
onban(source, channel, arg);
|
||
else
|
||
onunban(source, channel, arg);
|
||
}
|
||
else if (*change == 'l')
|
||
{
|
||
if (sign == '+' && atoi(arg) < 2)
|
||
{
|
||
if (chan->on && chan->AmChanOp)
|
||
{
|
||
changemode(channel, "-l", "", 0);
|
||
RemFlag(chan->mode, *change);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
change++;
|
||
if (*change == ' ')
|
||
{
|
||
change = ToWord(count, change);
|
||
count = 1;
|
||
}
|
||
}
|
||
if (chan != NULL)
|
||
{
|
||
if (desync)
|
||
{
|
||
part("", channel, "");
|
||
join("", channel, "");
|
||
}
|
||
CheckFlood(source, channel, 80);
|
||
flushmode(channel);
|
||
}
|
||
}
|
||
|
||
void onop(char *source, char *channel, char *target)
|
||
{
|
||
register auser *user;
|
||
register aluser *luser;
|
||
register achannel *chan;
|
||
char buffer[200];
|
||
|
||
chan = ToChannel(channel);
|
||
luser = ToLuser(source);
|
||
|
||
user = ToUser(channel, target);
|
||
|
||
if (!strcasecmp(mynick, target))
|
||
{
|
||
if (!chan)
|
||
{
|
||
log("ERROR: onop() channel not found!");
|
||
return;
|
||
}
|
||
|
||
chan->AmChanOp = 1;
|
||
}
|
||
else
|
||
{
|
||
#ifdef DEBUG
|
||
printf("OP for %s on %s\n", target, channel);
|
||
#endif
|
||
if (!user)
|
||
{
|
||
sprintf(buffer, "ERROR: onop() user not found (%s)",
|
||
target);
|
||
log(buffer);
|
||
return;
|
||
}
|
||
|
||
user->chanop = 1;
|
||
|
||
sprintf(buffer, "%s!%s@%s", user->N->nick, user->N->username, user->N->site);
|
||
|
||
if (luser && chan->on && (chan->flags & CFL_NOOP))
|
||
{
|
||
sprintf(buffer, "NoOp MODE! deopping %s and %s",
|
||
target, source);
|
||
log(buffer);
|
||
notice(target, replies[RPL_NOOP][chan->lang]);
|
||
notice(source, replies[RPL_NOOP][chan->lang]);
|
||
changemode(channel, "-o", target, 0);
|
||
changemode(channel, "-o", source, 0);
|
||
user->chanop = 0;
|
||
user = ToUser(channel, source);
|
||
if (user != NULL)
|
||
{
|
||
user->chanop = 0;
|
||
}
|
||
|
||
}
|
||
else if (luser && chan->on && (chan->flags & CFL_STRICTOP) &&
|
||
Access(channel, target) < OP_LEVEL)
|
||
{
|
||
sprintf(buffer, "StrictOp MODE! deopping %s and %s",
|
||
target, source);
|
||
log(buffer);
|
||
notice(target, "Only authenticated users may be op in StrictOp mode");
|
||
notice(source, "Only authenticated users may be op in StrictOp mode");
|
||
changemode(channel, "-o", target, 0);
|
||
user->chanop = 0;
|
||
if (Access(channel, source) < OP_LEVEL)
|
||
{
|
||
changemode(channel, "-o", source, 0);
|
||
user = ToUser(channel, source);
|
||
if (user != NULL)
|
||
{
|
||
user->chanop = 0;
|
||
}
|
||
}
|
||
|
||
}
|
||
else if (luser && chan->on && IsShit(channel, buffer, NULL, NULL) >= NO_OP_SHIT_LEVEL)
|
||
{
|
||
if (Access(channel, source) < ACCESS_BAN_PRIORITY)
|
||
{
|
||
sprintf(buffer, "%s is shitlisted (NO-OP LEVEL)!"
|
||
"Deopping %s and %s", target, target, source);
|
||
log(buffer);
|
||
notice(target, replies[RPL_CANTBEOP][chan->lang]);
|
||
notice(source, replies[RPL_CANTBEOPPED][chan->lang]);
|
||
changemode(channel, "-o", target, 0);
|
||
changemode(channel, "-o", source, 0);
|
||
user->chanop = 0;
|
||
user = ToUser(channel, source);
|
||
if (user != NULL)
|
||
user->chanop = 0;
|
||
|
||
sprintf(buffer, "%s %d", source, SUSPEND_TIME_FOR_OPPING_A_SHITLISTED_USER);
|
||
suspend("", channel, buffer);
|
||
}
|
||
else
|
||
{
|
||
unban(source, channel, target);
|
||
}
|
||
}
|
||
}
|
||
|
||
/** further tests should be put here **/
|
||
#ifdef NICKSERV
|
||
nserv_onop(channel, user);
|
||
#endif
|
||
}
|
||
|
||
void ondeop(char *source, char *channel, char *target, int *desync)
|
||
{
|
||
char buffer[200];
|
||
register auser *user1, *user2;
|
||
register achannel *chan;
|
||
register adeop *curr, *prec;
|
||
register int i;
|
||
|
||
chan = ToChannel(channel);
|
||
if (!chan)
|
||
{
|
||
log("ERROR: ondeop() channel not found!");
|
||
return;
|
||
}
|
||
|
||
user1 = ToUser(channel, source);
|
||
user2 = ToUser(channel, target);
|
||
|
||
if (chan->on && user1 == NULL)
|
||
{ /* desync! */
|
||
if (user2 != NULL)
|
||
{
|
||
user2->chanop = 0;
|
||
}
|
||
sprintf(buffer, "DESYNC detected! (%s deopped %s on %s)",
|
||
source, target, channel);
|
||
log(buffer);
|
||
|
||
/* part("",channel,"");
|
||
join("",channel,""); now doing this in ChangeMode */
|
||
|
||
*desync = 1;
|
||
|
||
return;
|
||
}
|
||
|
||
if (!strcasecmp(mynick, target))
|
||
{
|
||
if ((chan->flags & CFL_ALWAYSOP) &&
|
||
Access(channel, source) >= ALWAYSOP_OVERRIDE_LEVEL)
|
||
{
|
||
chan->flags &= ~CFL_ALWAYSOP;
|
||
sprintf(buffer, "AlwaysOp is turned off on %s (deopped by %s!%s@%s)",
|
||
channel, user1->N->nick, user1->N->username, user1->N->site);
|
||
log(buffer);
|
||
notice(source, replies[RPL_ALWAYSOPWASACTIVE][chan->lang]);
|
||
}
|
||
if (chan->flags & CFL_ALWAYSOP)
|
||
{
|
||
if (user1 != NULL)
|
||
{
|
||
sprintf(buffer, "DEOPPED by %s!%s@%s (%d) while AlwaysOp active on %s",
|
||
user1->N->nick, user1->N->username, user1->N->site,
|
||
Access(channel, source), channel);
|
||
log(buffer);
|
||
broadcast(buffer, 0);
|
||
i = IsShit(channel, source, NULL, NULL);
|
||
notice(source, replies[RPL_ALWAYSOP][chan->lang]);
|
||
switch (i)
|
||
{
|
||
case 0:
|
||
case 1:
|
||
case 2:
|
||
case 3:
|
||
case 4:
|
||
log("First warning");
|
||
notice(source, replies[RPL_DEOPPED1ST][chan->lang]);
|
||
changemode(channel, "-o", source, 0);
|
||
flushmode(channel);
|
||
user1->chanop = 0;
|
||
break;
|
||
|
||
case 5:
|
||
case 6:
|
||
case 7:
|
||
case 8:
|
||
case 9:
|
||
log("Second warning");
|
||
notice(source, replies[RPL_DEOPPED2ND][chan->lang]);
|
||
kick("", channel, source);
|
||
break;
|
||
|
||
default:
|
||
notice(source, "I warned you!");
|
||
changemode(channel, "-o", source, 0);
|
||
flushmode(channel);
|
||
user1->chanop = 0;
|
||
sprintf(buffer, "%s!%s@%s %d",
|
||
user1->N->nick, user1->N->username,
|
||
user1->N->site,
|
||
DEOPME_SUSPEND_TIME);
|
||
suspend("", channel, buffer);
|
||
sprintf(buffer, "Suspended %s!%s@%s on %s for repeatedly deopping me",
|
||
user1->N->nick, user1->N->username, user1->N->site, channel);
|
||
SpecLog(buffer);
|
||
broadcast(buffer, 0);
|
||
}
|
||
sprintf(buffer, "%s %d %d *** DEOP WHILE ALWAYSOP ACTIVE ***",
|
||
source, DEOP_SHITLIST_TIME,
|
||
(i < 10) ? i + 5 :
|
||
DEOP_SHITLIST_LEVEL);
|
||
AddToShitList("", channel, buffer, 0);
|
||
chan->AmChanOp = 0; /* to remove if I reop myself */
|
||
GetOps(channel);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
chan->AmChanOp = 0;
|
||
if (IsOpless(channel))
|
||
onopless(channel);
|
||
}
|
||
}
|
||
|
||
/* massdeop protection does NOT apply to the bot itself!
|
||
if(!strcasecmp(source,mynick)) return; obsolete */
|
||
|
||
/* No protection against server deop :/
|
||
Hey! I'm not gonna /squit it just for doing a deop!! ;) */
|
||
if (!user1)
|
||
return;
|
||
|
||
if (user2)
|
||
user2->chanop = 0;
|
||
|
||
chan = ToChannel(channel);
|
||
if (!chan)
|
||
{
|
||
log("ERROR: ondeop() channel not found!");
|
||
return;
|
||
}
|
||
|
||
/* If not on channel.. do NOT check for massdeop
|
||
*/
|
||
if (!chan->on)
|
||
return;
|
||
|
||
curr = user1->deophist;
|
||
prec = NULL;
|
||
|
||
/* ok.. let's free the *old* deops from history */
|
||
while (curr)
|
||
{
|
||
if (curr->time < (now - 15) || !strcasecmp(curr->nick, target))
|
||
{
|
||
if (prec)
|
||
{
|
||
prec->next = curr->next;
|
||
TTLALLOCMEM -= sizeof(adeop);
|
||
free(curr);
|
||
curr = prec->next;
|
||
}
|
||
else
|
||
{
|
||
user1->deophist = curr->next;
|
||
TTLALLOCMEM -= sizeof(adeop);
|
||
free(curr);
|
||
curr = user1->deophist;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
prec = curr;
|
||
curr = curr->next;
|
||
}
|
||
}
|
||
|
||
/* now store the deop in the user's deop history */
|
||
curr = (adeop *) MALLOC(sizeof(adeop));
|
||
strcpy(curr->nick, target);
|
||
curr->time = now;
|
||
curr->next = user1->deophist;
|
||
user1->deophist = curr;
|
||
|
||
/* now we count the number of deop in the user's history
|
||
if it's equal to the max number of deops per 15 seconds
|
||
interval.. activate the massdeop protection */
|
||
for (curr = user1->deophist, i = 0; curr; curr = curr->next, i++);
|
||
|
||
if (i == chan->MassDeopPro && chan->MassDeopPro != 0 && chan->on)
|
||
{
|
||
sprintf(buffer, "MASSDEOP from %s on %s", source, channel);
|
||
log(buffer);
|
||
notice(source, "### MASSDEOP PROTECTION ACTIVATED ###");
|
||
if (Access(channel, source) >= MASSDEOP_IMMUNE_LEVEL)
|
||
{
|
||
notice(source, "You are lucky your access is so high :P");
|
||
}
|
||
else
|
||
{
|
||
sprintf(buffer, "%s %d", source, MASSDEOP_SUSPEND_TIME);
|
||
suspend("", channel, buffer);
|
||
sprintf(buffer, "%s %d %d *** MASSDEOP ***", source,
|
||
MASSDEOP_SHITLIST_TIME,
|
||
MASSDEOP_SHITLIST_LEVEL);
|
||
AddToShitList("", channel, buffer, 0);
|
||
sprintf(buffer, "%s ### MASSDEOP PROTECTION ###", source);
|
||
kick("", channel, buffer);
|
||
}
|
||
}
|
||
}
|
||
|
||
void onban(char *nick, char *channel, char *pattern)
|
||
{
|
||
#ifdef DEBUG
|
||
printf("Wah! BAN FROM: %s\nON CHANNEL %s\nTARGET: %s\n",
|
||
nick, channel, pattern);
|
||
#endif
|
||
AddBan(channel, pattern);
|
||
}
|
||
|
||
void onunban(char *source, char *channel, char *pattern)
|
||
{
|
||
/*register achannel *chan; */
|
||
|
||
RemBan(channel, pattern);
|
||
|
||
/* mode -b no longer removes the ban from X's banlist
|
||
** it has to be removed with the 'unban' command.
|
||
chan=ToChannel(channel);
|
||
if(chan!=NULL && chan->on)
|
||
RemShitList(source,channel,pattern,1);
|
||
* */
|
||
}
|
||
|
||
void AddBan(char *channel, char *pattern)
|
||
{
|
||
register achannel *chan;
|
||
register aban *theban;
|
||
char buffer[200];
|
||
|
||
chan = ToChannel(channel);
|
||
if (chan == NULL)
|
||
{
|
||
sprintf(buffer, "ERROR: AddBan(): can't find %s", channel);
|
||
log(buffer);
|
||
return;
|
||
}
|
||
|
||
/* check if ban isn't already there */
|
||
for (theban = chan->bans; theban != NULL; theban = theban->next)
|
||
{
|
||
if (!strncasecmp(theban->pattern, pattern, 79))
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
|
||
theban = (aban *) MALLOC(sizeof(aban));
|
||
strncpy(theban->pattern, pattern, 79);
|
||
theban->pattern[79] = '\0';
|
||
theban->next = chan->bans;
|
||
chan->bans = theban;
|
||
}
|
||
|
||
|
||
void RemBan(char *channel, char *pattern)
|
||
{
|
||
register achannel *chan;
|
||
register aban **b, *theban = NULL;
|
||
|
||
chan = ToChannel(channel);
|
||
b = &chan->bans;
|
||
while (*b != NULL)
|
||
{
|
||
if (!strncasecmp((*b)->pattern, pattern, 79))
|
||
{
|
||
theban = *b;
|
||
*b = theban->next;
|
||
TTLALLOCMEM -= sizeof(aban);
|
||
free(theban);
|
||
}
|
||
else
|
||
{
|
||
b = &(*b)->next;
|
||
}
|
||
}
|
||
#ifdef DEBUG
|
||
if (theban == NULL)
|
||
{
|
||
printf("WARNING: RemBan(): pattern NOT found!!\n");
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
void changemode(char *channel, char *flag, char *arg, int AsServer)
|
||
{
|
||
register achannel *chan;
|
||
register modequeue *mode, *curr;
|
||
|
||
#ifdef DEBUG
|
||
printf("Queueing mode change for channel %s %s %s %d\n", channel, flag, arg, AsServer);
|
||
#endif
|
||
|
||
chan = ToChannel(channel);
|
||
if (!AsServer && (!chan || !chan->on))
|
||
return; /* not on the channel.. ignore */
|
||
|
||
/* first, cancel previous contradicting mode changes..
|
||
ex.. mode #test +o-o+o-o+o .. the bot won't do that.. */
|
||
|
||
mode = chan->modebuff;
|
||
while (mode)
|
||
{
|
||
if (!strcmp(arg, mode->arg) && flag[1] == mode->flag[1] &&
|
||
((flag[0] == '+' && mode->flag[0] == '-') ||
|
||
(flag[0] == '-' && mode->flag[0] == '+')))
|
||
{
|
||
if (mode->prev)
|
||
mode->prev->next = mode->next;
|
||
else
|
||
chan->modebuff = mode->next;
|
||
|
||
if (mode->next)
|
||
mode->next->prev = mode->prev;
|
||
|
||
curr = mode;
|
||
TTLALLOCMEM -= sizeof(modequeue);
|
||
free(curr);
|
||
}
|
||
else if (!strcmp(arg, mode->arg) && flag[1] == mode->flag[1] &&
|
||
flag[0] == mode->flag[0])
|
||
return;
|
||
mode = mode->next;
|
||
}
|
||
|
||
curr = (modequeue *) MALLOC(sizeof(modequeue));
|
||
strcpy(curr->arg, arg);
|
||
strcpy(curr->flag, flag);
|
||
curr->AsServer = AsServer;
|
||
curr->next = NULL;
|
||
|
||
for (mode = chan->modebuff; mode && mode->next; mode = mode->next);
|
||
|
||
if (mode)
|
||
{
|
||
curr->prev = mode;
|
||
mode->next = curr;
|
||
}
|
||
else
|
||
{
|
||
chan->modebuff = curr;
|
||
curr->prev = NULL;
|
||
}
|
||
}
|
||
|
||
void flushmode(char *channel)
|
||
{
|
||
char buffer[500];
|
||
register achannel *chan;
|
||
register modequeue *mode, *tmp;
|
||
char flags[20] = "";
|
||
char args[500] = "";
|
||
register char lastsign;
|
||
register int AsServer;
|
||
register int count = 0;
|
||
|
||
#ifdef DEBUG
|
||
printf("Flushing mode change buffer.. for channel %s\n", channel);
|
||
#endif
|
||
|
||
/* gotta pass thru the list twice:
|
||
* the first time, check for Server mode changes
|
||
* the second time, check for user mode changes
|
||
*/
|
||
|
||
chan = ToChannel(channel);
|
||
|
||
if (chan == NULL)
|
||
return;
|
||
|
||
#ifdef FAKE_UWORLD
|
||
#define ASSERVERMAX 2
|
||
#else
|
||
#define ASSERVERMAX 1
|
||
#endif
|
||
for (AsServer = ASSERVERMAX; AsServer >= 0; AsServer--)
|
||
{
|
||
#undef ASSERVERMAX
|
||
lastsign = '\0';
|
||
mode = chan->modebuff;
|
||
while (mode != NULL)
|
||
{
|
||
if (!strcmp(mode->flag, "-b"))
|
||
{
|
||
RemBan(channel, mode->arg);
|
||
}
|
||
else if (!strcmp(mode->flag, "+b"))
|
||
{
|
||
AddBan(channel, mode->arg);
|
||
}
|
||
if (AsServer == mode->AsServer)
|
||
{
|
||
if (mode->arg[0] != '\0')
|
||
{
|
||
count++;
|
||
strcat(args, " ");
|
||
strcat(args, mode->arg);
|
||
}
|
||
if (lastsign != mode->flag[0])
|
||
{
|
||
strcat(flags, mode->flag);
|
||
lastsign = mode->flag[0];
|
||
}
|
||
else
|
||
{
|
||
strcat(flags, mode->flag + 1);
|
||
}
|
||
if (mode->prev)
|
||
mode->prev->next = mode->next;
|
||
else
|
||
chan->modebuff = mode->next;
|
||
if (mode->next)
|
||
mode->next->prev = mode->prev;
|
||
tmp = mode;
|
||
mode = mode->next;
|
||
TTLALLOCMEM -= sizeof(modequeue);
|
||
free(tmp);
|
||
}
|
||
else
|
||
{
|
||
mode = mode->next;
|
||
}
|
||
|
||
if (count == MAX_MODE_PER_LINE || !mode)
|
||
{
|
||
if (AsServer == 0 && chan->AmChanOp && *flags != '\0')
|
||
{
|
||
sprintf(buffer, ":%s MODE %s %s%s\n",
|
||
mynick, channel, flags, args);
|
||
sendtoserv(buffer);
|
||
}
|
||
else if (AsServer == 1 && *flags != '\0')
|
||
{
|
||
sprintf(buffer, ":%s MODE %s %s%s %ld\n",
|
||
SERVERNAME, channel,
|
||
flags, args, chan->TS);
|
||
sendtoserv(buffer);
|
||
}
|
||
#ifdef FAKE_UWORLD
|
||
else if (AsServer == 2 && Uworld_status == 1 && *flags != '\0')
|
||
{
|
||
sprintf(buffer, ":%s MODE %s %s%s\n",
|
||
UFAKE_SERVER, channel,
|
||
flags, args);
|
||
sendtoserv(buffer);
|
||
}
|
||
#endif
|
||
count = *args = *flags = 0;
|
||
lastsign = '+';
|
||
}
|
||
}
|
||
}
|
||
}
|