// UserCommands.C -*- C++ -*- // Copyright (c) 1997, 1998 Etienne BERNARD // Copyright (C) 2002,2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #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 #include "Commands.H" #include "UserCommands.H" #include "DCCConnection.H" #include "DCCManager.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.next_token(); maskChannel = st.next_token(); level = st.next_token(); prot = st.next_token(); aop = st.next_token(); expiration = st.next_token(); passwd = st.next_token(); if (mask == "" || maskChannel == "" || level == "" || prot == "" || aop == "") { from->sendNotice("\002Invalid syntax for this command.\002"); return; } // if (!Utils::wildcard_p(mask)) { // mask = cnx->bot->getUserhost(channel, who); // if (mask == "") { // from->sendNotice(String("\002I can not find\002 ") + who); // return; // } // mask = Utils::make_wildcard(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::get_level(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::str2time(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::level2str(l) + " \002Protection:\002 " + Utils::prot2str(p) + " \002Auto-op:\002 " + Utils::bool2str(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.next_token(); int port = 6667; if (st.more_tokens_p()) { String temp = st.next_token(); 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.next_token(); maskChannel = st.next_token(); level = st.next_token(); expiration = st.next_token(); reason = Utils::trim_str (st.rest()); /* if (mask == "" || maskChannel == "" || level == "") { from->sendNotice("\002Invalid syntax for this command.\002"); return; } */ /* if (reason == "") reason = "You're on my shitlist, lamer"; */ /* if (!Utils::wildcard_p(mask)) { mask = cnx->bot->getUserhost(channel, who); if (mask == "") { from->sendNotice(String("\002I can not find\002 ") + who); return; } mask = Utils::make_wildcard(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::str2time(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 = Utils::to_upper (st.next_token()); String oldF = Utils::to_upper (st.next_token()); if (newF == "" || oldF == "") { from->sendNotice("\002Invalid syntax for this command.\002"); return; } // First, we check that the "new" function does not exist if (cnx->bot->userFunctions[newF]) { from->sendNotice(newF + " \002is already an alias.\002"); return; } // Next, we check that the "old" function exist if (!cnx->bot->userFunctions[oldF]) { from->sendNotice(String("\002I don't know the\002 ") + oldF + " \002command."); return; } // Fine, we do the binding cnx->bot->userFunctions[newF] = new userFunction (*cnx->bot->userFunctions[oldF]); 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::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.next_token(); // String maskChannel = st.next_token(); // String level = st.next_token(); // if (mask == "" || maskChannel == "" || level == "") { // from->sendNotice("\002Invalid syntax for this command.\002"); // return; // } // if (!Utils::wildcard_p(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::get_level(cnx->bot, from->getAddress())) { // from->sendNotice("\002You can not give a level greater than yours.\002"); // return; // } // if (Utils::get_level(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 >::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 (DCC_MAP::iterator it = cnx->bot->dccConnections->dcc_map.begin (); it != cnx->bot->dccConnections->dcc_map.end(); ++it) { from->sendNotice(String(it->second->dcc->get_nuh()).pad(32) + " " + String((long)(current_time - it->second->dcc->get_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.next_token(); String maskChannel = st.next_token(); if (mask == "" || maskChannel == "") { from->sendNotice("\002Invalid syntax for this command.\002"); return; } if (!Utils::wildcard_p(mask)) { mask = cnx->bot->getUserhost(channel, who); if (mask == "") { from->sendNotice(String("\002I can not find\002 ") + who); return; } mask = Utils::make_wildcard(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.next_token(); String maskChannel = st.next_token(); if (mask == "" || maskChannel == "") { from->sendNotice("\002Invalid syntax for this command.\002"); return; } if (!Utils::wildcard_p(mask)) { mask = cnx->bot->getUserhost(channel, who); if (mask == "") { from->sendNotice(String("\002I can not find\002 ") + who); return; } mask = Utils::make_wildcard(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::get_level(cnx->bot, from->getAddress()); String result = ""; int length = 0; std::map >::iterator it; for (it = cnx->bot->userFunctions.begin(); it != cnx->bot->userFunctions.end(); ++it) if ((*it).second->minLevel <= level) { result = result + (*it).first + " "; length += (*it).first.length() + 1; if (length >= 256) { from->sendNotice(result); result = ""; length = 0; } } if (result != "") from->sendNotice(result); from->sendNotice("\002Use\002 HELP \002for" " help about\002 "); return; } StringTokenizer st(rest); String command = Utils::to_upper (st.next_token()); 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 >::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.next_token(); if (!Utils::valid_channel_name_p(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.next_token(); if (Utils::wildcard_p(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::wildcard_p(who)) { Mask m(who); for (std::map >::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.next_token()); 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.next_token(); 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 >::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.next_token(); if (rest == "") { from->sendNotice(String("\002No nickname given.\002")); return; } if (!Utils::valid_nickname_p(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.next_token('@'); 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::wildcard_p(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::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::SetFloodRate(ServerConnection *cnx, Person *from, String channel, String rest) { Message m = Commands::SetFloodRate (cnx->bot, std::atoi (rest)); if (m.getCode ()) from->sendNotice (m.getMessage ()); else from->sendNotice ("Flood Rate set to:" + String(std::atol(rest))); } 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::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 >::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.next_token(); String t = st.next_token(); String dest; if (who == "" || t == "") { if (from) from->sendNotice("\002Invalid syntax for this command.\002"); return; } if (Utils::wildcard_p(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::wildcard_p(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::str2time(t)) == 0) { if (from) from->sendNotice(t + " \002is an invalid time.\002"); return; } dest = Utils::make_wildcard(dest); Mask m(dest); for (std::list::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::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.next_token(); String t = st.next_token(); 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::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) + " " + String(Utils::level2str((*it)->level)).pad(12) + " " + String(Utils::prot2str((*it)->prot)).pad(7) + " " + String(Utils::bool2str((*it)->aop)).pad(5) + " " + String(Utils::long2str ((*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::level2str(uli->level) + " \002Prot:\002 " + Utils::prot2str(uli->prot) + " \002Aop:\002 " + Utils::bool2str(uli->aop) + " \002Expired:\002 " + Utils::bool2str(!uli->isStillValid()) + " \002Ident:\002 " + (uli && !uli->identified ? "\026" : "") + Utils::bool2str(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.next_token(); 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::level2str(uli->level) + " \002Prot:\002 " + Utils::prot2str(uli->prot) + " \002Aop:\002 " + Utils::bool2str(uli->aop) + " \002Expired:\002 " + Utils::bool2str(!uli->isStillValid()) + " \002Ident:\002 " + Utils::bool2str(uli && uli->identified)); } else from->sendNotice(otherNick + " \002is not in the userlist for\002 " + channel); }