// Channel.C -*- C++ -*-
// Copyright (c) 1997, 1998 Etienne BERNARD
// Copyright (C) 2002 Clinton Ebadi
// 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
// 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.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "Macros.H"
#include "Utils.H"
#include "Channel.H"
#include "StringTokenizer.H"
#ifdef USESCRIPTS
#include "Interp.H"
#endif
Channel::Channel(ServerConnection *c,
String name, String wanted = "")
: channelName(name.toLower()), channelTopic(""),
lockedTopic(false), channelMode(0), channelLimit(0),
channelKey(""), keepModes(DEFAULT_KEEPMODES), wantedModes(wanted), count(0),
countOp(0), joined(false), doMode(true), gotWho(false), cnx(c)
{
#ifdef HAVE_STL_CLEAR
channelMemory.clear();
channelBanlist.clear();
#endif
if (c->bot->wantedChannels[channelName])
{
if (c->bot->wantedChannels[channelName]->keep != "")
keepModes = c->bot->wantedChannels[channelName]->keep;
if (c->bot->wantedChannels[channelName]->mode != "")
wantedModes = c->bot->wantedChannels[channelName]->mode;
}
}
Channel::~Channel()
{
User *u;
std::map<String, User *, std::less<String> >::iterator it;
while (channelMemory.size() != 0) {
it = channelMemory.begin();
u = (*it).second;
if (u && u->userListItem && u->userListItem->identified > 0)
u->userListItem->identified--;
channelMemory.erase(it);
delete u;
}
BanEntry *b;
std::vector<BanEntry *>::iterator it2;
while (channelBanlist.size() != 0) {
it2 = channelBanlist.begin();
b = *it2;
channelBanlist.erase(it2);
delete b;
}
}
void
Channel::addNick(String n, String uh, int mode, UserList *ul,
bool names)
{
if (User * u = getUser(n.toLower())) {
count--;
if (u->mode & User::OP_MODE)
countOp--;
channelMemory.erase(n.toLower());
delete u;
}
User *u;
if (names)
u = new User(n, mode);
else
u = new User(n, uh, channelName, mode, ul);
channelMemory[n.toLower()] = u;
if (u->userListItem) {
if (u->userListItem->identified)
u->userListItem->identified++;
else {
if (u->userListItem->passwd == "")
u->userListItem->identified = 1;
}
}
count++;
if (u->mode & User::OP_MODE)
countOp++;
}
void
Channel::delNick(String n)
{
n = n.toLower();
User *u = getUser(n);
if (!u)
return;
if (channelMemory[n]!=0) {
channelMemory.erase(n);
}
count--;
if (u->mode & User::OP_MODE)
countOp--;
if (u->userListItem && u->userListItem->identified > 0)
u->userListItem->identified--;
delete u;
}
void
Channel::changeNick(String on, String nn)
{
on = on.toLower();
User *u = getUser(on);
channelMemory.erase(on);
channelMemory[nn.toLower()] = u;
}
bool
Channel::hasNick(String n)
{
return getUser(n.toLower()) != 0;
}
User *
Channel::getUser(String n)
{
User *u;
n = n.toLower();
if ((u = channelMemory[n]) == 0) {
channelMemory.erase(n);
return 0;
}
return u;
}
void
Channel::addBan(String mask, std::time_t expiration)
{
for (std::vector<BanEntry *>::iterator it = channelBanlist.begin();
it != channelBanlist.end(); ++it)
if ((*it)->getMask() == mask) {
if (expiration > (*it)->getExpirationDate())
(*it)->setExpirationDate(expiration);
return;
}
channelBanlist.push_back(new BanEntry(mask, expiration));
}
void
Channel::delBan(String mask)
{
for (std::vector<BanEntry *>::iterator it = channelBanlist.begin();
it != channelBanlist.end(); ++it)
if (mask == (*it)->getMask()) {
BanEntry *b = *it;
channelBanlist.erase(it);
delete b;
break;
}
}
void
Channel::resynchModes()
{
cnx->queue->sendChannelMode(String("MODE ") + channelName +
" +" + cnx->bot->wantedChannels[channelName]->mode);
}
void
Channel::parseMode(Person *from, String mode)
{
char sign = '-';
StringTokenizer st(mode);
String m = st.nextToken(), n;
User *u = 0;
if (from)
u = getUser(from->getNick());
// u == 0 if it's a server mode
bool doNotObey = !u || (u->getProt() <= User::NO_PROT);
if (!gotWho)
doNotObey = false;
for (int i = 0; i < m.length(); i++)
switch(m[i]) {
case '+':
case '-':
sign = m[i];
break;
case 'p': sign =='+' ? channelMode |= PRIVATE :
channelMode &= ~PRIVATE;
if (keepModes.find('p') != -1 && doNotObey) {
if (sign == '-' && wantedModes.find('p') != -1)
cnx->queue->sendChannelMode(channelName, "+p", "");
else
cnx->queue->sendChannelMode(channelName, "-p", "");
}
break;
case 's': sign =='+' ? channelMode |= SECRET :
channelMode &= ~SECRET;
if (keepModes.find('s') != -1 && doNotObey) {
if (sign == '-' && wantedModes.find('s') != -1)
cnx->queue->sendChannelMode(channelName, "+s", "");
else
cnx->queue->sendChannelMode(channelName, "-s", "");
}
break;
case 'i': sign =='+' ? channelMode |= INVITE_ONLY :
channelMode &= ~INVITE_ONLY;
if (keepModes.find('i') != -1 && doNotObey) {
if (sign == '-' && wantedModes.find('i') != -1)
cnx->queue->sendChannelMode(channelName, "+i", "");
else
cnx->queue->sendChannelMode(channelName, "-i", "");
}
break;
case 't': sign =='+' ? channelMode |= TOPIC_RESTRICTED :
channelMode &= ~TOPIC_RESTRICTED;
if (keepModes.find('t') != -1 && doNotObey) {
if (sign == '-' && wantedModes.find('t') != -1)
cnx->queue->sendChannelMode(channelName, "+t", "");
else
cnx->queue->sendChannelMode(channelName, "-t", "");
}
break;
case 'n': sign =='+' ? channelMode |= EXTMSG_RESTRICTED :
channelMode &= ~EXTMSG_RESTRICTED;
if (keepModes.find('n') != -1 && doNotObey) {
if (sign == '-' && wantedModes.find('n') != -1)
cnx->queue->sendChannelMode(channelName, "+n", "");
else
cnx->queue->sendChannelMode(channelName, "-n", "");
}
break;
case 'm': sign =='+' ? channelMode |= MODERATED :
channelMode &= ~MODERATED;
if (keepModes.find('m') != -1 && doNotObey) {
if (sign == '-' && wantedModes.find('m') != -1)
cnx->queue->sendChannelMode(channelName, "+m", "");
else
cnx->queue->sendChannelMode(channelName, "-m", "");
}
break;
case 'l':
if (keepModes.find('l') != -1 && doNotObey) {
if (sign == '-' && wantedModes.find('l') != -1)
cnx->queue->sendChannelMode(channelName, "+l",
String((long)channelLimit));
else
cnx->queue->sendChannelMode(channelName, "-l", "");
}
channelLimit = (sign == '+' ? atoi(st.nextToken()) :
channelLimit = 0);
break;
case 'k':
channelKey = st.nextToken();
if (keepModes.find('k') != -1 && doNotObey) {
if (sign == '-' && wantedModes.find('k') != -1)
cnx->queue->sendChannelMode(channelName, "+k", channelKey);
else
cnx->queue->sendChannelMode(channelName, "-k", channelKey);
}
cnx->bot->wantedChannels[channelName]->key = (sign == '+' ? channelKey :
String(""));
break;
case 'o':
n = st.nextToken();
u = getUser(n);
if (joined)
sign == '+' ? countOp++ : countOp--;
if (!u)
break;
sign == '+' ? (u->mode |= User::OP_MODE) :
(u->mode &= ~User::OP_MODE);
if (sign == '-' && u->getProt() >= User::NO_DEOP) {
String fromNick = from->getNick();
User * v = getUser(fromNick);
if (u == v)
return;
if (v->getProt() < User::NO_DEOP)
cnx->queue->sendChannelMode(channelName, "-o", fromNick);
cnx->queue->sendChannelMode(channelName, "+o", n);
}
if (sign == '+') {
if (doNotObey && !from &&
u->getProt() < User::NO_DEOP && !u->getAop())
cnx->queue->sendChannelMode(channelName, "-o", n);
ShitEntry * se =
cnx->bot->shitList->getShit(n+"!"+cnx->bot->getUserhost(channelName, n),
channelName);
if (se && se->isStillValid() &&
se->getShitLevel() >= ShitEntry::SHIT_NOOP)
cnx->queue->sendChannelMode(channelName, "-o", n);
if (n.toLower() == cnx->bot->nickName.toLower() && doMode) {
doMode = false;
resynchModes();
}
}
break;
case 'v':
u = getUser(st.nextToken());
u->mode = (sign == '+' ? u->mode |= User::VOICE_MODE :
u->mode &= ~User::VOICE_MODE);
break;
case 'b':
String m = st.nextToken();
sign == '+' ? addBan(m) : delBan(m);
if (sign == '-') {
ShitEntry * se =
cnx->bot->shitList->getShit(m, channelName);
if (se && se->isStillValid() &&
se->getShitLevel() >= ShitEntry::SHIT_NODEBAN)
cnx->queue->sendChannelMode(channelName, "+b", m);
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1