// UserCommands.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 <fstream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ctype.h>
#ifndef _X_OPEN_SOURCE
#define _X_OPEN_SOURCE
#endif
#ifndef _X_OPEN_SOURCE_EXTENDED
#define _X_OPEN_SOURCE_EXTENDED 1
#endif
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif
#include <unistd.h>
#include "Commands.H"
#include "UserCommands.H"
#include "DCCConnection.H"
#include "Parser.H"
#include "Macros.H"
#include "StringTokenizer.H"
#include "Utils.H"
#include "ServerList.H"
#include "Server.H"
#ifdef NOCRYPT
char * crypt(const char *p, const char *s) { return p; }
#endif
void
UserCommands::Action(ServerConnection *cnx, Person *from,
String channel, String rest)
{
Message m = Commands::Action(cnx->bot, channel, rest);
if (m.getCode() != 0)
from->sendNotice(m.getMessage());
}
void
UserCommands::AddUser(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
String mask, who, maskChannel, level, prot,
aop, expiration, passwd;
mask = who = st.nextToken();
maskChannel = st.nextToken();
level = st.nextToken();
prot = st.nextToken();
aop = st.nextToken();
expiration = st.nextToken();
passwd = st.nextToken();
if (mask == "" || maskChannel == "" || level == "" ||
prot == "" || aop == "") {
from->sendNotice("\002Invalid syntax for this command.\002");
return;
}
// if (!Utils::isWildcard(mask)) {
// mask = cnx->bot->getUserhost(channel, who);
// if (mask == "") {
// from->sendNotice(String("\002I can not find\002 ") + who);
// return;
// }
// mask = Utils::makeWildcard(mask);
// }
// if (cnx->bot->userList->isInUserList(mask, maskChannel)) {
// from->sendNotice(who + " \002is already in userlist on channel(s)\002 " +
// maskChannel);
// return;
// }
int l, p;
bool a;
time_t e;
l = atoi((const char *)level);
if (l < 0 || l > User::FRIEND)
return;
if (l > Utils::getLevel(cnx->bot, from->getAddress())) {
from->sendNotice("\002You can not give a level greater than yours.\002");
return;
}
p = atoi((const char *)prot);
if (p < 0 || p > User::NO_DEOP)
return;
a = (bool)atoi((const char *)aop);
if (a != 0 && a != 1)
return;
e = Utils::strToTime(expiration);
if (!e)
e = -1;
// cnx->bot->userList->addUser(mask, maskChannel, l, p, a, e, passwd);
Message m =
Commands::AddUser (cnx->bot, who, maskChannel, l, p, a, e, passwd);
if (!m.getCode ())
{
from->sendNotice(String("\002Added\002 ") + mask +
" \002on channels\002 " + maskChannel);
from->sendNotice(String("\002Level:\002 ") +
Utils::levelToStr(l) +
" \002Protection:\002 " +
Utils::protToStr(p) +
" \002Auto-op:\002 " +
Utils::boolToStr(a));
}
else
from->sendNotice(m.getMessage ());
// cnx->bot->rehash();
}
void
UserCommands::AddServer(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() == 0) {
from->sendNotice("\002You must supply a server name.\002");
return;
}
StringTokenizer st(rest);
String serverName = st.nextToken();
int port = 6667;
if (st.hasMoreTokens()) {
String temp = st.nextToken();
port = atoi((const char *)temp);
}
Message m = Commands::AddServer(cnx->bot, serverName, port);
if (m.getCode() != 0)
from->sendNotice(m.getMessage());
else
from->sendNotice(String("\002Server\002 ") +
serverName + " \002on port\002 " +
String((long)port) + " \002has been added "
"to the server list.\002");
}
// FIXME: does this work now
void
UserCommands::AddShit(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
String mask, who, maskChannel, level, expiration, reason;
mask = who = st.nextToken();
maskChannel = st.nextToken();
level = st.nextToken();
expiration = st.nextToken();
reason = st.rest().trim();
/* if (mask == "" || maskChannel == "" || level == "") {
from->sendNotice("\002Invalid syntax for this command.\002");
return;
}
*/
/*
if (reason == "")
reason = "You're on my shitlist, lamer";
*/
/*
if (!Utils::isWildcard(mask)) {
mask = cnx->bot->getUserhost(channel, who);
if (mask == "") {
from->sendNotice(String("\002I can not find\002 ") + who);
return;
}
mask = Utils::makeWildcard(mask);
if (cnx->bot->shitList->getShit(mask, maskChannel)) {
from->sendNotice(mask + " \002is already in shitlist on channel(s)\002 " +
maskChannel);
return;
}
}
*/
int l;
time_t e;
l = atoi((const char *)level);
if (l < 0 || l > ShitEntry::SHIT_NODEBAN)
return;
e = Utils::strToTime(expiration);
if (!e)
e = -1;
/*
if (cnx->bot->userList->getMaxProt(mask, maskChannel) > 0) {
from->sendNotice(String("\002I can not add\002 ") + who +
" \002into the shitlist (protection).");
return;
}
cnx->bot->shitList->addShit(mask, maskChannel, l, e, reason);
*/
Message M = Commands::AddShit (cnx->bot, mask, maskChannel, l, e, reason);
if (!M.getCode ())
from->sendNotice(String("\002Added\002 ") + mask +
" \002on channels\002 " + maskChannel +
" \002into the shitlist.\002");
else
from->sendNotice (M.getMessage ());
}
// FIXME: Convert (and change ?)
void
UserCommands::Alias(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
String newF = st.nextToken().toUpper();
String oldF = st.nextToken().toUpper();
std::list<userFunction *>::iterator it;
if (newF == "" || oldF == "") {
from->sendNotice("\002Invalid syntax for this command.\002");
return;
}
// First, we check that the "new" function does not exist
for (it = cnx->bot->userFunctions.begin(); it !=
cnx->bot->userFunctions.end(); ++it)
if (newF == (*it)->name) {
from->sendNotice(newF + " \002is already an alias.\002");
return;
}
// Next, we check that the "old" function exist
bool found = false;
userFunction *u;
for (it = cnx->bot->userFunctions.begin(); it !=
cnx->bot->userFunctions.end(); ++it)
if (oldF == (*it)->name) {
found = true;
u = *it;
break;
}
if (!found) {
from->sendNotice(String("\002I don't know the\002 ") + oldF +
" \002command.");
return;
}
// Fine, we do the binding
cnx->bot->userFunctions.push_back(new
userFunction((char *)(const char
*)newF,
u->function,
u->minLevel,
u->needsChannelName));
from->sendNotice("\002Alias added.\002");
}
void
UserCommands::Ban(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() == 0) {
if (from)
from->sendNotice("\002No nick/mask specified.\002");
return;
}
Message m = Commands::Ban(cnx->bot, channel, rest);
if (m.getCode() != 0 && from)
from->sendNotice(m.getMessage());
}
void
UserCommands::BanList(ServerConnection *cnx, Person *from,
String channel, String rest)
{
time_t current = time(0);
Channel *c = cnx->bot->channelList->getChannel(channel);
from->sendNotice(String("\002Banlist for channel\002 ") +
channel + "\002:\002");
from->sendNotice("\002Mask Expires (seconds)\002");
for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
it != c->channelBanlist.end(); ++it)
if ((*it)->getExpirationDate() == -1)
from->sendNotice((*it)->getMask().pad(30) + " -1");
else
from->sendNotice((*it)->getMask().pad(30) + " " +
String((long)((*it)->getExpirationDate()-current)));
from->sendNotice("\002End of banlist.\002");
}
// void
// UserCommands::ChangeLevel(ServerConnection *cnx, Person *from,
// String channel, String rest)
// {
// StringTokenizer st(rest);
// String who;
// String mask = who = st.nextToken();
// String maskChannel = st.nextToken();
// String level = st.nextToken();
// if (mask == "" || maskChannel == "" || level == "") {
// from->sendNotice("\002Invalid syntax for this command.\002");
// return;
// }
// if (!Utils::isWildcard(mask)) {
// mask = cnx->bot->getUserhost(channel, who);
// if (mask == "") {
// from->sendNotice(String("\002I can not find\002 ") + who);
// return;
// }
// mask = from->getNick() + "!" + mask;
// }
// UserListItem *uli = cnx->bot->userList->getUserListItem(mask, maskChannel);
// if (!uli) {
// from->sendNotice(String("\002I can not find\002 ") + who +
// " \002on channel(s)\002 " + maskChannel +
// " \002in my userlist.\002");
// return;
// }
// int l = atoi((const char *)level);
// if (l < User::NONE || l > User::MASTER) {
// from->sendNotice("\002This is not a valid level.\002");
// return;
// }
// if (l > Utils::getLevel(cnx->bot, from->getAddress())) {
// from->sendNotice("\002You can not give a level greater than yours.\002");
// return;
// }
// if (Utils::getLevel(cnx->bot, from->getAddress()) < uli->level) {
// from->sendNotice("\002You can not change the level for a person "
// "whose level is greater than yours.\002");
// return;
// }
// uli->level = l;
// from->sendNotice("\002Level changed.\002");
// cnx->bot->rehash();
// }
void
UserCommands::Channels(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String result = "";
for (std::map<String, Channel *, std::less<String> >::iterator it =
cnx->bot->channelList->begin();
it != cnx->bot->channelList->end(); ++it)
result = result + (*it).first + " ";
if (result == "")
from->sendNotice("\002I am not on any channel.\002");
else
from->sendNotice(String("\002I am currently on channel(s):\002 ") +
+ result);
}
void
UserCommands::Cycle(ServerConnection *cnx, Person *from,
String channel, String rest)
{
Message m = Commands::Cycle(cnx->bot, channel);
if (m.getCode() != 0)
from->sendNotice(m.getMessage());
}
void
UserCommands::DCCList(ServerConnection *cnx, Person *from,
String channel, String rest)
{
time_t current_time = time(0);
from->sendNotice("\002DCClist:\002");
from->sendNotice("\002Hostname Last used\002");
for (std::list<DCCConnection *>::iterator it =
cnx->bot->dccConnections.begin();
it != cnx->bot->dccConnections.end();
++it) {
from->sendNotice((*it)->nuh.pad(32) + " " +
String((long)(current_time -
(*it)->lastSpoken)));
}
from->sendNotice("\002End of dcclist.\002");
}
void
UserCommands::Deban(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() == 0) {
from->sendNotice("\002No nick/mask specified.\002");
return;
}
Message m = Commands::Deban(cnx->bot, channel, rest);
if (m.getCode() != 0)
from->sendNotice(m.getMessage());
}
void
UserCommands::DelServer(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() == 0) {
from->sendNotice("\002You need to supply a server number"
" for this command.\002");
return;
}
int serverNumber = atoi(rest);
Message m = Commands::DelServer(cnx->bot, serverNumber);
if (m.getCode() != 0)
from->sendNotice(m.getMessage());
else
from->sendNotice(String("Deleted server ") +
cnx->bot->serverList->get(serverNumber)->getHostName() +
" (" + String((long)cnx->bot->serverList->get(serverNumber)->getPort()) +
").");
}
// FIXME: Convert
void
UserCommands::DelUser(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
String who;
String mask = who = st.nextToken();
String maskChannel = st.nextToken();
if (mask == "" || maskChannel == "") {
from->sendNotice("\002Invalid syntax for this command.\002");
return;
}
if (!Utils::isWildcard(mask)) {
mask = cnx->bot->getUserhost(channel, who);
if (mask == "") {
from->sendNotice(String("\002I can not find\002 ") + who);
return;
}
mask = Utils::makeWildcard(mask);
}
if (!cnx->bot->userList->isInUserList(mask, maskChannel)) {
from->sendNotice(mask + " \002is not in userlist on channel(s)\002 " +
maskChannel);
return;
}
cnx->bot->userList->removeUser(mask, maskChannel);
from->sendNotice(who + " \002has been removed from the userlist.\002");
cnx->bot->rehash();
}
// FIXME: Convert
void
UserCommands::DelShit(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
String who;
String mask = who = st.nextToken();
String maskChannel = st.nextToken();
if (mask == "" || maskChannel == "") {
from->sendNotice("\002Invalid syntax for this command.\002");
return;
}
if (!Utils::isWildcard(mask)) {
mask = cnx->bot->getUserhost(channel, who);
if (mask == "") {
from->sendNotice(String("\002I can not find\002 ") + who);
return;
}
mask = Utils::makeWildcard(mask);
}
if (!cnx->bot->shitList->getShit(mask, maskChannel)) {
from->sendNotice(mask + " \002is not in shitlist on channel(s)\002 " +
maskChannel);
return;
}
cnx->bot->shitList->delShit(mask, maskChannel);
from->sendNotice(who + " \002has been removed from the shitlist.\002");
}
void
UserCommands::Deop(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String target = rest;
if (target.length() == 0)
target = from->getNick();
Message m = Commands::Deop(cnx->bot, channel, target);
if (m.getCode() != 0)
from->sendNotice(m.getMessage());
}
void
UserCommands::Die(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String reason;
if (rest.length() == 0)
reason = "Leaving";
else
reason = rest;
Commands::Die(cnx->bot, reason);
}
void
UserCommands::Do(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() != 0)
Commands::Do(cnx->bot, rest);
}
#ifdef USESCRIPTS
void
UserCommands::Execute(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() != 0)
Interp::Execute(cnx->bot, rest);
}
#endif
void
UserCommands::Help(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() == 0) {
from->sendNotice("\002Available topics for you are:\002");
int level = Utils::getLevel(cnx->bot, from->getAddress());
String result = "";
int length = 0;
std::list<userFunction *>::iterator it;
for (it = cnx->bot->userFunctions.begin(); it != cnx->bot->userFunctions.end(); ++it)
if ((*it)->minLevel <= level) {
result = result + (*it)->name + " ";
length += strlen((*it)->name) + 1;
if (length >= 256) {
from->sendNotice(result);
result = ""; length = 0;
}
}
if (result != "")
from->sendNotice(result);
from->sendNotice("\002Use\002 HELP <command> \002for"
" help about\002 <command>");
return;
}
StringTokenizer st(rest);
String command = st.nextToken().toUpper();
std::ifstream helpFile(cnx->bot->helpFileName);
if (!helpFile) {
from->sendNotice(String("\002Error: I can not find the "
"help file\002 ") +
cnx->bot->helpFileName);
return;
}
String buf;
while (!helpFile.eof()) {
helpFile >> buf;
if (buf.subString(0, command.length()) == String(":") + command) {
buf = buf.subString(1);
from->sendNotice(String("\002Help for\002 ") + command +
"\002:\002");
while (buf != "") {
from->sendNotice(buf);
helpFile >> buf;
}
from->sendNotice("\002End of help.\002");
return;
}
}
from->sendNotice(String("\002No such topic (\002") +
command + "\002).\002");
}
void
UserCommands::Ident(ServerConnection *cnx, Person *from,
String channel, String rest)
{
Channel *c = cnx->bot->channelList->getChannel(channel);
if (rest.length() <= 2) {
from->sendNotice("\002No password specified or password "
"too short.\002");
return;
}
User * u = c->getUser(from->getNick());
if (!u) {
from->sendNotice(String("\002You can identify yourself on"
" channel\002 ") + channel +
" \002only if you are on the channel.\002");
return;
}
if (u->userListItem && u->userListItem->identified) {
from->sendNotice(String("\002You are already identified on"
" channel\002 ") + channel);
return;
}
if (!u->userListItem) {
from->sendNotice("\002You are not in my userlist.\002");
return;
}
if (u->userListItem->passwd ==
crypt((const char *)rest, (const char *)u->userListItem->passwd)) {
// For each channel, we increment identification counter
for (std::map<String, Channel *, std::less<String> >::iterator it =
cnx->bot->channelList->begin();
it != cnx->bot->channelList->end(); ++it)
u->userListItem->identified++;
from->sendNotice("\002You are now identified.\002");
} else
from->sendNotice("\002This is a wrong password.\002");
}
void
UserCommands::Invite(ServerConnection *cnx, Person *from,
String channel, String rest)
{
Message m = Commands::Invite(cnx->bot, channel, rest);
if (m.getCode() < 0)
from->sendNotice(m.getMessage());
from->sendNotice(String("\002Inviting\002 ") + rest + " \002on channel\002 " + channel);
}
// FIXME: Convert
void
UserCommands::Join(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
channel = st.nextToken();
if (!Utils::isValidChannelName(channel)) {
from->sendNotice(String("\002") + channel +
" is not a valid channel name\002");
return;
}
// We change the key only if we are not on the channel. We don't trust
// the user...
if (!cnx->bot->channelList->getChannel(channel)) {
if (cnx->bot->wantedChannels[channel])
cnx->bot->wantedChannels[channel]->key = st.rest();
else {
cnx->bot->wantedChannels[channel] = new wantedChannel("", "", st.rest());
}
}
cnx->queue->sendJoin(channel, cnx->bot->wantedChannels[channel]->key);
}
// FIXME: Convert
void
UserCommands::Keep(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
if (rest.length() == 0) {
from->sendNotice("\002No channel modes specified.\002");
return;
}
cnx->bot->channelList->getChannel(channel)->keepModes = rest;
from->sendNotice(String("\002Keeping modes\002 ") +
rest + " \002on channel\002 " +
channel);
}
// FIXME: Convert
void
UserCommands::Kick(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
Channel * c = cnx->bot->channelList->getChannel(channel);
if (rest.length() == 0) {
from->sendNotice("\002No nick specified.\002");
return;
}
StringTokenizer st(rest);
String who = st.nextToken();
if (Utils::isWildcard(who)) {
User * u = c->getUser(nick);
if (!u)
return;
if (u->getLevel() < User::TRUSTED_USER) {
from->sendNotice("\002You need an higher level to "
"use wildcards.\002");
return;
}
}
if (!cnx->bot->iAmOp(channel)) {
from->sendNotice(String("\002I am not channel op on\002 ") +
channel);
return;
}
if (Utils::isWildcard(who)) {
Mask m(who);
for (std::map<String, User *, std::less<String> >::iterator it =
c->channelMemory.begin();
it != c->channelMemory.end();
++it)
if (m.matches((*it).second->nick + "!" +
(*it).second->userhost) &&
(*it).second->getProt() < User::NO_KICK)
cnx->queue->sendKick(channel, (*it).second->nick, st.rest());
} else {
User * u = c->getUser(who);
if (!u) {
from->sendNotice(String("\002I can not find\002 ") +
who + " \002on\002 " + channel);
return;
}
if (u->getProt() < User::NO_KICK)
cnx->queue->sendKick(channel, who, st.rest());
else
from->sendNotice(String("\002I can not kick\002 ") +
who + " \002on\002 " + channel +
" \002(protected).\002");
}
}
// FIXME: Convert
void
UserCommands::KickBan(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
Ban(cnx, 0, channel, st.nextToken());
Kick(cnx, from, channel, rest);
}
void
UserCommands::Load(ServerConnection *cnx, Person *from,
String channel, String rest)
{
cnx->bot->shitList->read();
cnx->bot->userList->read();
cnx->bot->userList->addUserFirst(cnx->bot->nickName + "!" + cnx->bot->userHost, "*", 0, 3, true, -1, "");
cnx->bot->rehash();
from->sendNotice("\002Userlist and shitlist loaded.\002");
}
#ifdef USESCRIPTS
void
UserCommands::LoadScript(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() != 0)
Interp::LoadScript(cnx->bot, rest);
}
#endif
// FIXME: Convert
void
UserCommands::Lock(ServerConnection *cnx, Person *from,
String channel, String rest)
{
cnx->bot->channelList->getChannel(channel)->lockedTopic = true;
from->sendNotice(String("\002Locking topic for channel\002 ") +
channel);
}
// FIXME: Convert
void
UserCommands::Mode(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
if (rest.length() == 0) {
from->sendNotice("\002I need a parameter for this command.\002");
return;
}
if (!cnx->bot->iAmOp(channel)) {
from->sendNotice(String("\002I am not channel op on\002 ") +
channel);
return;
}
cnx->queue->sendChannelMode(String("MODE ") + channel + " " + rest);
}
void
UserCommands::Msg(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
String who = st.nextToken();
String message = st.rest();
Message m = Commands::Msg(cnx->bot, who, message);
if (m.getCode() != 0)
from->sendNotice(m.getMessage());
}
void
UserCommands::Names(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
String result = "";
int length = 0;
Channel *c = cnx->bot->channelList->getChannel(channel);
std::map<String, User *, std::less<String> >::iterator it;
from->sendNotice(String("\002Names on ") +
channel + ":\002");
for (it = c->channelMemory.begin();
it != c->channelMemory.end(); ++it) {
result = result +
((*it).second->mode & User::OP_MODE ? "@" :
((*it).second->mode & User::VOICE_MODE ? "+" : "")) +
(*it).second->nick + " ";
length += (*it).first.length() + 1;
if (length >= 256) {
from->sendNotice(result);
result = ""; length = 0;
}
}
if (result != "")
from->sendNotice(result);
from->sendNotice("\002End of names.\002");
}
// FIXME: Convert
void
UserCommands::NextServer(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (cnx->bot->serverList->size() == 0) {
from->sendNotice("\002Server list is empty !\002");
return;
}
if (cnx->bot->serverList->size() == 1) {
from->sendNotice("\002Server list has only one item. Use"
" \"reconnect\" to force reconnection.\002");
return;
}
if (cnx->bot->canChangeServer()) {
cnx->queue->sendQuit("Changing server");
cnx->bot->nextServer();
}
else
from->sendNotice("\002I can not change server without"
" losing op on a channel I am on.\002");
}
// FIXME: Convert
void
UserCommands::Nick(ServerConnection *cnx, Person *from,
String channel, String rest)
{
// We parse the parameters
StringTokenizer st(rest);
String nick = st.nextToken();
if (rest == "") {
from->sendNotice(String("\002No nickname given.\002"));
return;
}
if (!Utils::isValidNickName(nick)) {
from->sendNotice(String("\002") + nick +
" is not a valid nickname\002");
return;
}
cnx->bot->wantedNickName = nick;
cnx->queue->sendNick(nick);
}
void
UserCommands::NsLookup(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String target;
if (rest.length() == 0) {
from->sendNotice("\002You need to supply a nick or an "
"host for this command.\002");
return;
}
if (rest.find('.') == -1) {
StringTokenizer st(cnx->bot->getUserhost("", rest));
st.nextToken('@');
target = st.rest();
if (target.length() == 0) {
from->sendNotice(String("\002I could not find\002 ") +
target);
return;
}
} else
target = rest;
struct hostent * host;
struct in_addr iaddr;
if (isdigit(target[0])) { // An IP ?
iaddr.s_addr = inet_addr((const char *)target);
host = gethostbyaddr((char *)(&iaddr),
sizeof(struct in_addr),
AF_INET);
if (host) {
from->sendNotice(target +
" \002is the IP address of\002 " +
host->h_name);
return;
}
} else {
host = gethostbyname((const char *)target);
if (host) {
memcpy((char *)&iaddr, (char *)host->h_addr,
host->h_length);
from->sendNotice(target + " \002has\002 " +
inet_ntoa(iaddr) + " \002for IP address.\002");
return;
}
}
from->sendNotice(String("\002I could not find host\002 ") +
target);
}
// FIXME: Convert
void
UserCommands::Op(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
if (!cnx->bot->iAmOp(channel)) {
from->sendNotice(String("\002I am not channel op on\002 ") +
channel);
return;
}
if (Utils::isWildcard(rest)) {
from->sendNotice("\002Mass op is not allowed.\002");
return;
}
String target;
if (rest.length() == 0)
target = nick;
else
target = rest;
User *u = cnx->bot->channelList->getChannel(channel)->getUser(target);
if (!u) {
from->sendNotice(String("\002I cannot find\002 ") + target + " \002on channel\002 " + channel);
return;
}
ShitEntry *se = cnx->bot->shitList->getShit(target, channel);
if (se && se->isStillValid() && se->getShitLevel() >= ShitEntry::SHIT_NOOP) {
from->sendNotice(String("\002I can not op\002 ")+target+" \002on channel\002 "+channel+" \002(shitlist).\002");
return;
}
if (!(u->mode & User::OP_MODE))
cnx->queue->sendChannelMode(channel, "+o", target);
else {
if (target == nick)
from->sendNotice(String("\002You are already channel "
"operator on\002 ") + channel);
else
from->sendNotice(target + " \002is already channel "
"operator on\002 " + channel);
}
}
// FIXME: Convert
void
UserCommands::Part(ServerConnection *cnx, Person *from,
String channel, String rest)
{
wantedChannel *w = cnx->bot->wantedChannels[channel];
cnx->bot->wantedChannels.erase(channel);
delete w;
cnx->queue->sendPart(channel);
}
void
UserCommands::Password(ServerConnection *cnx, Person *from,
String channel, String rest)
{
Channel *c = cnx->bot->channelList->getChannel(channel);
if (rest.length() == 0) {
from->sendNotice("\002No password.\002");
return;
}
User * u = c->getUser(from->getNick());
if (!u) {
from->sendNotice(String("\002To change your password for\002") +
channel + "\002, you need to be on the "
"channel.\002");
return;
}
if (!u->userListItem) {
from->sendNotice("\002You are not in my userlist.\002");
return;
}
if (rest.toLower() == "none") {
u->userListItem->passwd = "";
from->sendNotice("\002Password cleared.\002");
return;
}
static char saltChars[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
char salt[3];
srand(time(0));
salt[0] = saltChars[rand() % 64];
salt[1] = saltChars[rand() % 64];
salt[2] = '\0';
u->userListItem->passwd = crypt((const char *)rest, salt);
from->sendNotice("\002Password changed.\002");
}
void
UserCommands::Save(ServerConnection *cnx, Person *from,
String channel, String rest)
{
cnx->bot->userList->save();
cnx->bot->shitList->save();
from->sendNotice("\002Userlist and shitlist saved.\002");
}
// FIXME: Convert
void
UserCommands::Say(ServerConnection *cnx, Person *from,
String channel, String rest)
{
if (rest.length() != 0)
cnx->queue->sendPrivmsg(channel, rest);
}
// FIXME: Convert
void
UserCommands::Server(ServerConnection *cnx, Person *from,
String channel, String rest)
{
int serverNumber;
String nick = from->getNick();
if (rest.length() == 0) {
from->sendNotice("\002You need to supply a server number for this command.\002");
return;
}
serverNumber = atoi(rest);
if (serverNumber < 0 || serverNumber >= cnx->bot->serverList->size()) {
from->sendNotice(String((long)serverNumber) +
" \002is an invalid server number (see the serverlist).\002");
return;
}
if (cnx->bot->canChangeServer()) {
cnx->queue->sendQuit("Changing server");
cnx->queue->flush();
cnx->bot->connect(serverNumber);
}
else
from->sendNotice("\002I can not change server without losing op on a channel I am on.\002");
}
void
UserCommands::ServerList(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
from->sendNotice("\002Server list:\002");
long l = 0;
String s;
for (std::vector<class Server *>::iterator it =
cnx->bot->serverList->v.begin();
it != cnx->bot->serverList->v.end();
++it) {
s = (*it) == cnx->server ? "\026" : "";
from->sendNotice(s + String(l++) + s + " " +
(*it)->getHostName() +
" (" + String((long)((*it)->getPort())) +
")");
}
from->sendNotice("\002End of server list.\002");
}
void
UserCommands::SetVersion(ServerConnection *cnx, Person *from,
String channel, String rest)
{
Message m = Commands::SetVersion(cnx->bot, rest);
if (m.getCode() < 0)
from->sendNotice(m.getMessage());
}
void
UserCommands::ShitList(ServerConnection *cnx, Person *from,
String channel, String rest)
{
from->sendNotice("\002Shitlist:\002");
from->sendNotice("\002Mask Channel Level Expires Reason\002");
for (std::list<ShitEntry *>::iterator it = cnx->bot->shitList->l.begin();
it != cnx->bot->shitList->l.end();
it++)
from->sendNotice((*it)->shitMask.getMask().pad(25) + " " +
(*it)->shitChannelMask.getMask().pad(10) + " " +
String((long)(*it)->shitLevel).pad(9) + " " +
String((long)(*it)->expirationDate).pad(9) + " " +
(*it)->shitReason);
from->sendNotice("\002End of shitlist.\002");
}
void
UserCommands::SpyList(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
from->sendNotice("\002Spy list:\002");
for (std::map<String, Person *, std::less<String> >::iterator it =
cnx->bot->spyList.begin(); it != cnx->bot->spyList.end(); ++it)
from->sendNotice((*it).first);
from->sendNotice("\002End of spy list.\002");
}
void
UserCommands::SpyMessage(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
if (cnx->bot->spyList.find(nick) != cnx->bot->spyList.end()) {
from->sendNotice("\002You are already spying messages.\002");
return;
}
Person *f = from->copy();
f->keepAlive();
cnx->bot->spyList[nick.toLower()] = f;
from->sendNotice("\002You have been added to the spy list.\002");
}
// FIXME: Convert
void
UserCommands::Reconnect(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
if (cnx->bot->canChangeServer()) {
cnx->queue->sendQuit("Reconnecting");
cnx->bot->reconnect();
}
else
from->sendNotice("\002I can not change server without losing op on a channel I am on.\002");
}
void
UserCommands::RSpyMessage(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick().toLower();
if (cnx->bot->spyList.find(nick) == cnx->bot->spyList.end()) {
from->sendNotice("\002You are not in the spy list.\002");
return;
}
delete cnx->bot->spyList[nick];
cnx->bot->spyList.erase(nick);
from->sendNotice("\002You have been removed from the "
"spy list.\002");
}
// FIXME: Convert
void
UserCommands::Unlock(ServerConnection *cnx, Person *from,
String channel, String rest)
{
cnx->bot->channelList->getChannel(channel)->lockedTopic = false;
from->sendNotice(String("\002Unlocking topic for channel\002 ") +
channel);
}
void
UserCommands::Stats(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
from->sendNotice(String("\002Keeping modes\002 ") +
cnx->bot->channelList->getChannel(channel)->keepModes + " \002on channel\002 " +
channel);
}
// FIXME: Convert
void
UserCommands::TBan(ServerConnection *cnx, Person *from,
String channel, String rest)
{
Channel * c = cnx->bot->channelList->getChannel(channel);
StringTokenizer st(rest);
String who = st.nextToken();
String t = st.nextToken();
String dest;
if (who == "" || t == "") {
if (from)
from->sendNotice("\002Invalid syntax for this command.\002");
return;
}
if (Utils::isWildcard(who) && from) {
User * u = c->getUser(from->getNick());
if (u && u->getLevel() < User::TRUSTED_USER) {
if (from)
from->sendNotice("\002You need an higher level to use"
" wildcards.\002");
return;
}
}
if (!cnx->bot->iAmOp(channel)) {
if (from)
from->sendNotice(String("\002I am not channel op on\002 ") +
channel);
return;
}
if (!Utils::isWildcard(who))
dest = cnx->bot->getUserhost(channel, who);
else
dest = who;
if (dest == "") {
if (from)
from->sendNotice(String("\002I can not find\002 ") + who);
return;
}
time_t w;
if ((w = Utils::strToTime(t)) == 0) {
if (from)
from->sendNotice(t + " \002is an invalid time.\002");
return;
}
dest = Utils::makeWildcard(dest);
Mask m(dest);
for (std::list<UserListItem *>::iterator it = cnx->bot->userList->l.begin();
it != cnx->bot->userList->l.end();
it++)
if (m.matches((*it)->mask) &&
(*it)->channelMask.matches(channel) &&
(*it)->prot >= User::NO_BAN) {
if (from)
from->sendNotice(String("\002I can not ban\002 ") +
who + " \002on channel\002 " +
channel + " \002(protection).\002");
return;
}
for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
it != c->channelBanlist.end(); ++it)
if (m.matches((*it)->banMask))
cnx->queue->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
cnx->bot->channelList->getChannel(channel)->addBan(dest, w);
cnx->queue->sendChannelMode(channel, "+b", dest);
cnx->bot->todoList->addDeban(channel, dest, (time_t)w);
}
// FIXME: Convert
void
UserCommands::TKBan(ServerConnection *cnx, Person *from,
String channel, String rest)
{
StringTokenizer st(rest);
String who = st.nextToken();
String t = st.nextToken();
TBan(cnx, 0, channel, who + " " + t);
Kick(cnx, from, channel, who + " " + st.rest());
}
// FIXME: Convert
void
UserCommands::Topic(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
if (rest.length() == 0) {
if (cnx->bot->channelList->getChannel(channel)->channelTopic == "")
from->sendNotice(String("\002No topic is set for channel\002 ") +
channel + "\002.\002");
else
from->sendNotice(String("\002Topic for\002 ") +
channel + " \002is:\002 " +
cnx->bot->channelList->getChannel(channel)->channelTopic);
} else {
if (cnx->bot->channelList->getChannel(channel)->lockedTopic)
from->sendNotice(String("\002Topic is locked on channel\002 ") +
channel);
else
cnx->queue->sendTopic(channel, rest);
}
}
void
UserCommands::UserList(ServerConnection *cnx, Person *from,
String channel, String rest)
{
from->sendNotice("\002Userlist:\002");
from->sendNotice("\002Mask Channel Level Prot Aop Expires\002");
for (std::list<UserListItem *>::iterator it = cnx->bot->userList->l.begin();
it != cnx->bot->userList->l.end();
it++)
from->sendNotice((*it)->mask.getMask().pad(25) + " " +
(*it)->channelMask.getMask().pad(10) + " " +
Utils::levelToStr((*it)->level).pad(12) + " " +
Utils::protToStr((*it)->prot).pad(7) + " " +
Utils::boolToStr((*it)->aop).pad(5) + " " +
String((long)(*it)->expirationDate));
from->sendNotice("\002End of userlist.\002");
}
void
UserCommands::Who(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
User * u = cnx->bot->channelList->getChannel(channel)->getUser(nick);
UserListItem * uli;
if (u)
uli = u->userListItem;
else
uli = cnx->bot->userList->getUserListItem(from->getAddress(),
channel);
if (uli) {
from->sendNotice(String("\002You are\002 ") +
uli->mask.getMask() + " \002on\002 " +
uli->channelMask.getMask());
from->sendNotice(String("\002Lvl:\002 ") +
Utils::levelToStr(uli->level) +
" \002Prot:\002 " +
Utils::protToStr(uli->prot) +
" \002Aop:\002 " +
Utils::boolToStr(uli->aop) +
" \002Expired:\002 " +
Utils::boolToStr(!uli->isStillValid()) +
" \002Ident:\002 " +
(uli && !uli->identified ? "\026" : "") +
Utils::boolToStr(uli && uli->identified) +
(uli && !uli->identified ? "\026" : ""));
} else
from->sendNotice(String("\002You are not in the userlist for\002 ") +
channel);
}
void
UserCommands::Whois(ServerConnection *cnx, Person *from,
String channel, String rest)
{
String nick = from->getNick();
if (!rest.length()) {
from->sendNotice("\002No nick specified.\002");
return;
}
StringTokenizer st(rest);
String otherNick = st.nextToken();
User * u = cnx->bot->channelList->getChannel(channel)->getUser(otherNick);
UserListItem * uli;
if (u)
uli = u->userListItem;
else
uli = cnx->bot->userList->getUserListItem(otherNick + "!" +
cnx->bot->getUserhost(channel,
otherNick),
channel);
if (uli) {
from->sendNotice(otherNick +
" \002is\002 " + uli->mask.getMask() +
" \002on\002 " + uli->channelMask.getMask());
from->sendNotice(String("\002Lvl:\002 ") +
Utils::levelToStr(uli->level) +
" \002Prot:\002 " +
Utils::protToStr(uli->prot) +
" \002Aop:\002 " +
Utils::boolToStr(uli->aop) +
" \002Expired:\002 " +
Utils::boolToStr(!uli->isStillValid()) +
" \002Ident:\002 " +
Utils::boolToStr(uli && uli->identified));
} else
from->sendNotice(otherNick +
" \002is not in the userlist for\002 " +
channel);
}
syntax highlighted by Code2HTML, v. 0.9.1