1 // UserCommands.C -*- C++ -*-
2 // Copyright (c) 1997, 1998 Etienne BERNARD
3 // Copyright (C) 2002,2005 Clinton Ebadi
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 #include "UserCommands.H"
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
40 #ifndef _X_OPEN_SOURCE
41 #define _X_OPEN_SOURCE
43 #ifndef _X_OPEN_SOURCE_EXTENDED
44 #define _X_OPEN_SOURCE_EXTENDED 1
54 #include "ChannelList.H"
56 #include "DCCConnection.H"
57 #include "DCCManager.H"
58 #include "DCCPerson.H"
65 #include "ServerConnection.H"
66 #include "ServerList.H"
67 #include "ShitEntry.H"
68 #include "StringTokenizer.H"
79 char * crypt(const char *p, const char *s) { return p; }
83 UserCommands::Action(ServerConnection *cnx, Person *from,
84 String channel, String rest)
86 Message m = Commands::Action(cnx->bot, channel, rest);
88 from->sendNotice(m.getMessage());
92 UserCommands::AddUser(ServerConnection *cnx, Person *from,
93 String channel, String rest)
95 StringTokenizer st(rest);
96 String mask, who, maskChannel, level, prot,
97 aop, expiration, passwd;
99 mask = who = st.next_token();
100 maskChannel = st.next_token();
101 level = st.next_token();
102 prot = st.next_token();
103 aop = st.next_token();
104 expiration = st.next_token();
105 passwd = st.next_token();
107 if (mask == "" || maskChannel == "" || level == "" ||
108 prot == "" || aop == "") {
109 from->sendNotice("\002Invalid syntax for this command.\002");
113 // if (!Utils::wildcard_p(mask)) {
114 // mask = cnx->bot->getUserhost(channel, who);
116 // from->sendNotice(String("\002I can not find\002 ") + who);
119 // mask = Utils::make_wildcard(mask);
122 // if (cnx->bot->userList->isInUserList(mask, maskChannel)) {
123 // from->sendNotice(who + " \002is already in userlist on channel(s)\002 " +
132 l = atoi((const char *)level);
133 if (l < 0 || l > User::FRIEND)
135 if (l > Utils::get_level(cnx->bot, from->getAddress())) {
136 from->sendNotice("\002You can not give a level greater than yours.\002");
139 p = atoi((const char *)prot);
140 if (p < 0 || p > User::NO_DEOP)
142 a = (bool)atoi((const char *)aop);
143 if (a != 0 && a != 1)
146 e = Utils::str2time(expiration);
151 // cnx->bot->userList->addUser(mask, maskChannel, l, p, a, e, passwd);
154 Commands::AddUser (cnx->bot, who, maskChannel, l, p, a, e, passwd);
157 from->sendNotice(String("\002Added\002 ") + mask +
158 " \002on channels\002 " + maskChannel);
159 from->sendNotice(String("\002Level:\002 ") +
160 Utils::level2str(l) +
161 " \002Protection:\002 " +
163 " \002Auto-op:\002 " +
167 from->sendNotice(m.getMessage ());
169 // cnx->bot->rehash();
173 UserCommands::AddServer(ServerConnection *cnx, Person *from,
174 String channel, String rest)
176 if (rest.length() == 0) {
177 from->sendNotice("\002You must supply a server name.\002");
181 StringTokenizer st(rest);
182 String serverName = st.next_token();
185 if (st.more_tokens_p()) {
186 String temp = st.next_token();
187 port = atoi((const char *)temp);
190 Message m = Commands::AddServer(cnx->bot, serverName, port);
191 if (m.getCode() != 0)
192 from->sendNotice(m.getMessage());
194 from->sendNotice(String("\002Server\002 ") +
195 serverName + " \002on port\002 " +
196 String((long)port) + " \002has been added "
197 "to the server list.\002");
200 // FIXME: does this work now
202 UserCommands::AddShit(ServerConnection *cnx, Person *from,
203 String channel, String rest)
205 StringTokenizer st(rest);
206 String mask, who, maskChannel, level, expiration, reason;
208 mask = who = st.next_token();
209 maskChannel = st.next_token();
210 level = st.next_token();
211 expiration = st.next_token();
212 reason = Utils::trim_str (st.rest());
214 /* if (mask == "" || maskChannel == "" || level == "") {
215 from->sendNotice("\002Invalid syntax for this command.\002");
222 reason = "You're on my shitlist, lamer";
226 if (!Utils::wildcard_p(mask)) {
227 mask = cnx->bot->getUserhost(channel, who);
229 from->sendNotice(String("\002I can not find\002 ") + who);
232 mask = Utils::make_wildcard(mask);
233 if (cnx->bot->shitList->getShit(mask, maskChannel)) {
234 from->sendNotice(mask + " \002is already in shitlist on channel(s)\002 " +
243 l = atoi((const char *)level);
244 if (l < 0 || l > ShitEntry::SHIT_NODEBAN)
247 e = Utils::str2time(expiration);
253 if (cnx->bot->userList->getMaxProt(mask, maskChannel) > 0) {
254 from->sendNotice(String("\002I can not add\002 ") + who +
255 " \002into the shitlist (protection).");
259 cnx->bot->shitList->addShit(mask, maskChannel, l, e, reason);
262 Message M = Commands::AddShit (cnx->bot, mask, maskChannel, l, e, reason);
264 from->sendNotice(String("\002Added\002 ") + mask +
265 " \002on channels\002 " + maskChannel +
266 " \002into the shitlist.\002");
268 from->sendNotice (M.getMessage ());
271 // FIXME: Convert (and change ?)
273 UserCommands::Alias(ServerConnection *cnx, Person *from,
274 String channel, String rest)
276 StringTokenizer st(rest);
277 String newF = Utils::to_upper (st.next_token());
278 String oldF = Utils::to_upper (st.next_token());
280 if (newF == "" || oldF == "") {
281 from->sendNotice("\002Invalid syntax for this command.\002");
285 // First, we check that the "new" function does not exist
286 if (cnx->bot->userFunctions[newF]) {
287 from->sendNotice(newF + " \002is already an alias.\002");
291 // Next, we check that the "old" function exist
292 if (!cnx->bot->userFunctions[oldF])
294 from->sendNotice(String("\002I don't know the\002 ") + oldF +
299 // Fine, we do the binding
300 cnx->bot->userFunctions[newF] =
301 new userFunction (*cnx->bot->userFunctions[oldF]);
303 from->sendNotice("\002Alias added.\002");
307 UserCommands::Ban(ServerConnection *cnx, Person *from,
308 String channel, String rest)
310 if (rest.length() == 0) {
312 from->sendNotice("\002No nick/mask specified.\002");
316 Message m = Commands::Ban(cnx->bot, channel, rest);
317 if (m.getCode() != 0 && from)
318 from->sendNotice(m.getMessage());
322 UserCommands::BanList(ServerConnection *cnx, Person *from,
323 String channel, String rest)
325 time_t current = time(0);
326 Channel *c = cnx->bot->channelList->getChannel(channel);
327 from->sendNotice(String("\002Banlist for channel\002 ") +
328 channel + "\002:\002");
329 from->sendNotice("\002Mask Expires (seconds)\002");
330 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
331 it != c->channelBanlist.end(); ++it)
332 if ((*it)->getExpirationDate() == -1)
333 from->sendNotice((*it)->getMask().getMask().pad(30) + " -1");
335 from->sendNotice((*it)->getMask().getMask().pad(30) + " " +
336 String((long)((*it)->getExpirationDate()-current)));
337 from->sendNotice("\002End of banlist.\002");
341 // UserCommands::ChangeLevel(ServerConnection *cnx, Person *from,
342 // String channel, String rest)
344 // StringTokenizer st(rest);
347 // String mask = who = st.next_token();
348 // String maskChannel = st.next_token();
349 // String level = st.next_token();
351 // if (mask == "" || maskChannel == "" || level == "") {
352 // from->sendNotice("\002Invalid syntax for this command.\002");
356 // if (!Utils::wildcard_p(mask)) {
357 // mask = cnx->bot->getUserhost(channel, who);
359 // from->sendNotice(String("\002I can not find\002 ") + who);
362 // mask = from->getNick() + "!" + mask;
365 // UserListItem *uli = cnx->bot->userList->getUserListItem(mask, maskChannel);
368 // from->sendNotice(String("\002I can not find\002 ") + who +
369 // " \002on channel(s)\002 " + maskChannel +
370 // " \002in my userlist.\002");
374 // int l = atoi((const char *)level);
376 // if (l < User::NONE || l > User::MASTER) {
377 // from->sendNotice("\002This is not a valid level.\002");
381 // if (l > Utils::get_level(cnx->bot, from->getAddress())) {
382 // from->sendNotice("\002You can not give a level greater than yours.\002");
386 // if (Utils::get_level(cnx->bot, from->getAddress()) < uli->level) {
387 // from->sendNotice("\002You can not change the level for a person "
388 // "whose level is greater than yours.\002");
393 // from->sendNotice("\002Level changed.\002");
394 // cnx->bot->rehash();
398 UserCommands::Channels(ServerConnection *cnx, Person *from,
399 String channel, String rest)
403 for (std::map<String, Channel *, std::less<String> >::iterator it =
404 cnx->bot->channelList->begin();
405 it != cnx->bot->channelList->end(); ++it)
406 result = result + (*it).first + " ";
409 from->sendNotice("\002I am not on any channel.\002");
411 from->sendNotice(String("\002I am currently on channel(s):\002 ") +
416 UserCommands::Cycle(ServerConnection *cnx, Person *from,
417 String channel, String rest)
419 Message m = Commands::Cycle(cnx->bot, channel);
420 if (m.getCode() != 0)
421 from->sendNotice(m.getMessage());
425 UserCommands::DCCList(ServerConnection *cnx, Person *from,
426 String channel, String rest)
428 time_t current_time = time(0);
430 from->sendNotice("\002DCClist:\002");
431 from->sendNotice("\002Hostname Last used\002");
433 for (DCC_MAP::iterator it =
434 cnx->bot->dccConnections->dcc_map.begin ();
435 it != cnx->bot->dccConnections->dcc_map.end();
437 from->sendNotice(String(it->second->dcc->get_nuh()).pad(32) + " " +
438 String((long)(current_time -
439 it->second->dcc->get_lastSpoken())));
442 from->sendNotice("\002End of dcclist.\002");
446 UserCommands::Deban(ServerConnection *cnx, Person *from,
447 String channel, String rest)
449 if (rest.length() == 0) {
450 from->sendNotice("\002No nick/mask specified.\002");
454 Message m = Commands::Deban(cnx->bot, channel, rest);
455 if (m.getCode() != 0)
456 from->sendNotice(m.getMessage());
460 UserCommands::DelServer(ServerConnection *cnx, Person *from,
461 String channel, String rest)
463 if (rest.length() == 0) {
464 from->sendNotice("\002You need to supply a server number"
465 " for this command.\002");
469 int serverNumber = atoi(rest);
471 Message m = Commands::DelServer(cnx->bot, serverNumber);
472 if (m.getCode() != 0)
473 from->sendNotice(m.getMessage());
475 from->sendNotice(String("Deleted server ") +
476 cnx->bot->serverList->get(serverNumber)->getHostName() +
477 " (" + String((long)cnx->bot->serverList->get(serverNumber)->getPort()) +
483 UserCommands::DelUser(ServerConnection *cnx, Person *from,
484 String channel, String rest)
486 StringTokenizer st(rest);
489 String mask = who = st.next_token();
490 String maskChannel = st.next_token();
492 if (mask == "" || maskChannel == "") {
493 from->sendNotice("\002Invalid syntax for this command.\002");
497 if (!Utils::wildcard_p(mask)) {
498 mask = cnx->bot->getUserhost(channel, who);
500 from->sendNotice(String("\002I can not find\002 ") + who);
503 mask = Utils::make_wildcard(mask);
506 if (!cnx->bot->userList->isInUserList(mask, maskChannel)) {
507 from->sendNotice(mask + " \002is not in userlist on channel(s)\002 " +
512 cnx->bot->userList->removeUser(mask, maskChannel);
513 from->sendNotice(who + " \002has been removed from the userlist.\002");
519 UserCommands::DelShit(ServerConnection *cnx, Person *from,
520 String channel, String rest)
522 StringTokenizer st(rest);
525 String mask = who = st.next_token();
526 String maskChannel = st.next_token();
528 if (mask == "" || maskChannel == "") {
529 from->sendNotice("\002Invalid syntax for this command.\002");
533 if (!Utils::wildcard_p(mask)) {
534 mask = cnx->bot->getUserhost(channel, who);
536 from->sendNotice(String("\002I can not find\002 ") + who);
539 mask = Utils::make_wildcard(mask);
542 if (!cnx->bot->shitList->getShit(mask, maskChannel)) {
543 from->sendNotice(mask + " \002is not in shitlist on channel(s)\002 " +
548 cnx->bot->shitList->delShit(mask, maskChannel);
549 from->sendNotice(who + " \002has been removed from the shitlist.\002");
553 UserCommands::Deop(ServerConnection *cnx, Person *from,
554 String channel, String rest)
556 String target = rest;
558 if (target.length() == 0)
559 target = from->getNick();
561 Message m = Commands::Deop(cnx->bot, channel, target);
562 if (m.getCode() != 0)
563 from->sendNotice(m.getMessage());
567 UserCommands::Die(ServerConnection *cnx, Person *from,
568 String channel, String rest)
572 if (rest.length() == 0)
577 Commands::Die(cnx->bot, reason);
581 UserCommands::Do(ServerConnection *cnx, Person *from,
582 String channel, String rest)
584 if (rest.length() != 0)
585 Commands::Do(cnx->bot, rest);
590 UserCommands::Execute(ServerConnection *cnx, Person *from,
591 String channel, String rest)
593 if (rest.length() != 0)
594 Interp::Execute(cnx->bot, rest);
599 UserCommands::Help(ServerConnection *cnx, Person *from,
600 String channel, String rest)
602 if (rest.length() == 0) {
603 from->sendNotice("\002Available topics for you are:\002");
604 int level = Utils::get_level(cnx->bot, from->getAddress());
607 std::map<std::string, class userFunction*,
608 std::less<std::string> >::iterator it;
610 for (it = cnx->bot->userFunctions.begin();
611 it != cnx->bot->userFunctions.end(); ++it)
613 if ((*it).second->minLevel <= level)
615 result = result + (*it).first + " ";
616 length += (*it).first.length() + 1;
620 from->sendNotice(result);
621 result = ""; length = 0;
626 from->sendNotice(result);
627 from->sendNotice("\002Use\002 HELP <command> \002for"
628 " help about\002 <command>");
632 StringTokenizer st(rest);
633 String command = Utils::to_upper (st.next_token());
634 std::ifstream helpFile(cnx->bot->helpFileName);
637 from->sendNotice(String("\002Error: I can not find the "
639 cnx->bot->helpFileName);
644 while (!helpFile.eof()) {
646 if (buf.subString(0, command.length()) == String(":") + command) {
647 buf = buf.subString(1);
648 from->sendNotice(String("\002Help for\002 ") + command +
651 from->sendNotice(buf);
654 from->sendNotice("\002End of help.\002");
659 from->sendNotice(String("\002No such topic (\002") +
660 command + "\002).\002");
664 UserCommands::Ident(ServerConnection *cnx, Person *from,
665 String channel, String rest)
667 Channel *c = cnx->bot->channelList->getChannel(channel);
669 if (rest.length() <= 2) {
670 from->sendNotice("\002No password specified or password "
675 User * u = c->getUser(from->getNick());
677 from->sendNotice(String("\002You can identify yourself on"
678 " channel\002 ") + channel +
679 " \002only if you are on the channel.\002");
683 if (u->userListItem && u->userListItem->identified) {
684 from->sendNotice(String("\002You are already identified on"
685 " channel\002 ") + channel);
689 if (!u->userListItem) {
690 from->sendNotice("\002You are not in my userlist.\002");
694 if (u->userListItem->passwd ==
695 crypt((const char *)rest, (const char *)u->userListItem->passwd)) {
696 // For each channel, we increment identification counter
697 for (std::map<String, Channel *, std::less<String> >::iterator it =
698 cnx->bot->channelList->begin();
699 it != cnx->bot->channelList->end(); ++it)
700 u->userListItem->identified++;
702 from->sendNotice("\002You are now identified.\002");
704 from->sendNotice("\002This is a wrong password.\002");
708 UserCommands::Invite(ServerConnection *cnx, Person *from,
709 String channel, String rest)
711 Message m = Commands::Invite(cnx->bot, channel, rest);
713 from->sendNotice(m.getMessage());
714 from->sendNotice(String("\002Inviting\002 ") + rest + " \002on channel\002 " + channel);
719 UserCommands::Join(ServerConnection *cnx, Person *from,
720 String channel, String rest)
722 StringTokenizer st(rest);
723 channel = st.next_token();
725 if (!Utils::valid_channel_name_p(channel)) {
726 from->sendNotice(String("\002") + channel +
727 " is not a valid channel name\002");
731 // We change the key only if we are not on the channel. We don't trust
733 if (!cnx->bot->channelList->getChannel(channel)) {
734 if (cnx->bot->wantedChannels[channel])
735 cnx->bot->wantedChannels[channel]->key = st.rest();
737 cnx->bot->wantedChannels[channel] = new wantedChannel("", "", st.rest());
740 cnx->queue->sendJoin(channel, cnx->bot->wantedChannels[channel]->key);
745 UserCommands::Keep(ServerConnection *cnx, Person *from,
746 String channel, String rest)
748 String nick = from->getNick();
750 if (rest.length() == 0) {
751 from->sendNotice("\002No channel modes specified.\002");
755 cnx->bot->channelList->getChannel(channel)->keepModes = rest;
756 from->sendNotice(String("\002Keeping modes\002 ") +
757 rest + " \002on channel\002 " +
763 UserCommands::Kick(ServerConnection *cnx, Person *from,
764 String channel, String rest)
766 String nick = from->getNick();
768 Channel * c = cnx->bot->channelList->getChannel(channel);
770 if (rest.length() == 0) {
771 from->sendNotice("\002No nick specified.\002");
775 StringTokenizer st(rest);
776 String who = st.next_token();
778 if (Utils::wildcard_p(who)) {
779 User * u = c->getUser(nick);
782 if (u->getLevel() < User::TRUSTED_USER) {
783 from->sendNotice("\002You need an higher level to "
784 "use wildcards.\002");
789 if (!cnx->bot->iAmOp(channel)) {
790 from->sendNotice(String("\002I am not channel op on\002 ") +
795 if (Utils::wildcard_p(who)) {
797 for (std::map<String, User *, std::less<String> >::iterator it =
798 c->channelMemory.begin();
799 it != c->channelMemory.end();
801 if (m.matches((*it).second->nick + "!" +
802 (*it).second->userhost) &&
803 (*it).second->getProt() < User::NO_KICK)
804 cnx->queue->sendKick(channel, (*it).second->nick, st.rest());
806 User * u = c->getUser(who);
808 from->sendNotice(String("\002I can not find\002 ") +
809 who + " \002on\002 " + channel);
812 if (u->getProt() < User::NO_KICK)
813 cnx->queue->sendKick(channel, who, st.rest());
815 from->sendNotice(String("\002I can not kick\002 ") +
816 who + " \002on\002 " + channel +
817 " \002(protected).\002");
823 UserCommands::KickBan(ServerConnection *cnx, Person *from,
824 String channel, String rest)
826 StringTokenizer st(rest);
828 Ban(cnx, 0, channel, st.next_token());
829 Kick(cnx, from, channel, rest);
833 UserCommands::Load(ServerConnection *cnx, Person *from,
834 String channel, String rest)
836 cnx->bot->shitList->read();
837 cnx->bot->userList->read();
838 cnx->bot->userList->addUserFirst(cnx->bot->nickName + "!" + cnx->bot->userHost, "*", 0, 3, true, -1, "");
840 from->sendNotice("\002Userlist and shitlist loaded.\002");
845 UserCommands::LoadScript(ServerConnection *cnx, Person *from,
846 String channel, String rest)
848 if (rest.length() != 0)
849 Interp::LoadScript(cnx->bot, rest);
855 UserCommands::Lock(ServerConnection *cnx, Person *from,
856 String channel, String rest)
858 cnx->bot->channelList->getChannel(channel)->lockedTopic = true;
859 from->sendNotice(String("\002Locking topic for channel\002 ") +
865 UserCommands::Mode(ServerConnection *cnx, Person *from,
866 String channel, String rest)
868 String nick = from->getNick();
870 if (rest.length() == 0) {
871 from->sendNotice("\002I need a parameter for this command.\002");
875 if (!cnx->bot->iAmOp(channel)) {
876 from->sendNotice(String("\002I am not channel op on\002 ") +
881 cnx->queue->sendChannelMode(String("MODE ") + channel + " " + rest);
885 UserCommands::Msg(ServerConnection *cnx, Person *from,
886 String channel, String rest)
888 StringTokenizer st(rest);
889 String who = st.next_token();
890 String message = st.rest();
892 Message m = Commands::Msg(cnx->bot, who, message);
893 if (m.getCode() != 0)
894 from->sendNotice(m.getMessage());
898 UserCommands::Names(ServerConnection *cnx, Person *from,
899 String channel, String rest)
901 String nick = from->getNick();
904 Channel *c = cnx->bot->channelList->getChannel(channel);
905 std::map<String, User *, std::less<String> >::iterator it;
907 from->sendNotice(String("\002Names on ") +
910 for (it = c->channelMemory.begin();
911 it != c->channelMemory.end(); ++it) {
913 ((*it).second->mode & User::OP_MODE ? "@" :
914 ((*it).second->mode & User::VOICE_MODE ? "+" : "")) +
915 (*it).second->nick + " ";
916 length += (*it).first.length() + 1;
918 from->sendNotice(result);
919 result = ""; length = 0;
924 from->sendNotice(result);
926 from->sendNotice("\002End of names.\002");
931 UserCommands::NextServer(ServerConnection *cnx, Person *from,
932 String channel, String rest)
934 if (cnx->bot->serverList->size() == 0) {
935 from->sendNotice("\002Server list is empty !\002");
939 if (cnx->bot->serverList->size() == 1) {
940 from->sendNotice("\002Server list has only one item. Use"
941 " \"reconnect\" to force reconnection.\002");
945 if (cnx->bot->canChangeServer()) {
946 cnx->queue->sendQuit("Changing server");
947 cnx->bot->nextServer();
950 from->sendNotice("\002I can not change server without"
951 " losing op on a channel I am on.\002");
956 UserCommands::Nick(ServerConnection *cnx, Person *from,
957 String channel, String rest)
959 // We parse the parameters
960 StringTokenizer st(rest);
961 String nick = st.next_token();
964 from->sendNotice(String("\002No nickname given.\002"));
968 if (!Utils::valid_nickname_p (cnx->bot, nick)) {
969 from->sendNotice(String("\002") + nick +
970 " is not a valid nickname\002");
974 cnx->bot->wantedNickName = nick;
975 cnx->queue->sendNick(nick);
979 UserCommands::NsLookup(ServerConnection *cnx, Person *from,
980 String channel, String rest)
984 if (rest.length() == 0) {
985 from->sendNotice("\002You need to supply a nick or an "
986 "host for this command.\002");
990 if (rest.find('.') == -1) {
991 StringTokenizer st(cnx->bot->getUserhost("", rest));
994 if (target.length() == 0) {
995 from->sendNotice(String("\002I could not find\002 ") +
1002 struct hostent * host;
1003 struct in_addr iaddr;
1005 if (isdigit(target[0])) { // An IP ?
1006 iaddr.s_addr = inet_addr((const char *)target);
1007 host = gethostbyaddr((char *)(&iaddr),
1008 sizeof(struct in_addr),
1011 from->sendNotice(target +
1012 " \002is the IP address of\002 " +
1017 host = gethostbyname((const char *)target);
1019 std::memcpy((char *)&iaddr, (char *)host->h_addr,
1021 from->sendNotice(target + " \002has\002 " +
1022 inet_ntoa(iaddr) + " \002for IP address.\002");
1027 from->sendNotice(String("\002I could not find host\002 ") +
1033 UserCommands::Op(ServerConnection *cnx, Person *from,
1034 String channel, String rest)
1036 String nick = from->getNick();
1038 if (!cnx->bot->iAmOp(channel)) {
1039 from->sendNotice(String("\002I am not channel op on\002 ") +
1044 if (Utils::wildcard_p(rest)) {
1045 from->sendNotice("\002Mass op is not allowed.\002");
1051 if (rest.length() == 0)
1056 User *u = cnx->bot->channelList->getChannel(channel)->getUser(target);
1058 from->sendNotice(String("\002I cannot find\002 ") + target + " \002on channel\002 " + channel);
1062 ShitEntry *se = cnx->bot->shitList->getShit(target, channel);
1063 if (se && se->isStillValid() && se->getShitLevel() >= ShitEntry::SHIT_NOOP) {
1064 from->sendNotice(String("\002I can not op\002 ")+target+" \002on channel\002 "+channel+" \002(shitlist).\002");
1068 if (!(u->mode & User::OP_MODE))
1069 cnx->queue->sendChannelMode(channel, "+o", target);
1072 from->sendNotice(String("\002You are already channel "
1073 "operator on\002 ") + channel);
1075 from->sendNotice(target + " \002is already channel "
1076 "operator on\002 " + channel);
1082 UserCommands::Part(ServerConnection *cnx, Person *from,
1083 String channel, String rest)
1085 wantedChannel *w = cnx->bot->wantedChannels[channel];
1086 cnx->bot->wantedChannels.erase(channel);
1088 cnx->queue->sendPart(channel);
1092 UserCommands::Password(ServerConnection *cnx, Person *from,
1093 String channel, String rest)
1095 Channel *c = cnx->bot->channelList->getChannel(channel);
1097 if (rest.length() == 0) {
1098 from->sendNotice("\002No password.\002");
1102 User * u = c->getUser(from->getNick());
1104 from->sendNotice(String("\002To change your password for\002") +
1105 channel + "\002, you need to be on the "
1110 if (!u->userListItem) {
1111 from->sendNotice("\002You are not in my userlist.\002");
1115 if (rest.toLower() == "none") {
1116 u->userListItem->passwd = "";
1117 from->sendNotice("\002Password cleared.\002");
1121 static char saltChars[] = "abcdefghijklmnopqrstuvwxyz"
1122 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
1125 salt[0] = saltChars[rand() % 64];
1126 salt[1] = saltChars[rand() % 64];
1129 u->userListItem->passwd = crypt((const char *)rest, salt);
1130 from->sendNotice("\002Password changed.\002");
1134 UserCommands::Save(ServerConnection *cnx, Person *from,
1135 String channel, String rest)
1137 cnx->bot->userList->save();
1138 cnx->bot->shitList->save();
1139 from->sendNotice("\002Userlist and shitlist saved.\002");
1144 UserCommands::Say(ServerConnection *cnx, Person *from,
1145 String channel, String rest)
1147 if (rest.length() != 0)
1148 cnx->queue->sendPrivmsg(channel, rest);
1153 UserCommands::Server(ServerConnection *cnx, Person *from,
1154 String channel, String rest)
1157 String nick = from->getNick();
1159 if (rest.length() == 0) {
1160 from->sendNotice("\002You need to supply a server number for this command.\002");
1164 serverNumber = atoi(rest);
1166 if (serverNumber < 0 || serverNumber >= cnx->bot->serverList->size()) {
1167 from->sendNotice(String((long)serverNumber) +
1168 " \002is an invalid server number (see the serverlist).\002");
1172 if (cnx->bot->canChangeServer()) {
1173 cnx->queue->sendQuit("Changing server");
1174 cnx->queue->flush();
1175 cnx->bot->connect(serverNumber);
1178 from->sendNotice("\002I can not change server without losing op on a channel I am on.\002");
1182 UserCommands::ServerList(ServerConnection *cnx, Person *from,
1183 String channel, String rest)
1185 String nick = from->getNick();
1187 from->sendNotice("\002Server list:\002");
1190 for (std::vector<class Server *>::iterator it =
1191 cnx->bot->serverList->v.begin();
1192 it != cnx->bot->serverList->v.end();
1194 s = (*it) == cnx->server ? "\026" : "";
1195 from->sendNotice(s + String(l++) + s + " " +
1196 (*it)->getHostName() +
1197 " (" + String((long)((*it)->getPort())) +
1200 from->sendNotice("\002End of server list.\002");
1205 UserCommands::SetFloodRate(ServerConnection *cnx, Person *from,
1206 String channel, String rest)
1208 Message m = Commands::SetFloodRate (cnx->bot, std::atoi (rest));
1210 from->sendNotice (m.getMessage ());
1212 from->sendNotice ("Flood Rate set to:" + String(std::atol(rest)));
1216 UserCommands::SetVersion(ServerConnection *cnx, Person *from,
1217 String channel, String rest)
1219 Message m = Commands::SetVersion(cnx->bot, rest);
1221 if (m.getCode() < 0)
1223 Commands::Notice (cnx->bot, from->getNick (), m.getMessage());
1228 UserCommands::ShitList(ServerConnection *cnx, Person *from,
1229 String channel, String rest)
1231 from->sendNotice("\002Shitlist:\002");
1232 from->sendNotice("\002Mask Channel Level Expires Reason\002");
1234 for (std::list<ShitEntry *>::iterator it = cnx->bot->shitList->l.begin();
1235 it != cnx->bot->shitList->l.end();
1237 from->sendNotice((*it)->shitMask.getMask().pad(25) + " " +
1238 (*it)->shitChannelMask.getMask().pad(10) + " " +
1239 String((long)(*it)->shitLevel).pad(9) + " " +
1240 String((long)(*it)->expirationDate).pad(9) + " " +
1243 from->sendNotice("\002End of shitlist.\002");
1247 UserCommands::SpyList(ServerConnection *cnx, Person *from,
1248 String channel, String rest)
1250 String nick = from->getNick();
1252 from->sendNotice("\002Spy list:\002");
1254 for (std::map<String, Person *, std::less<String> >::iterator it =
1255 cnx->bot->spyList.begin(); it != cnx->bot->spyList.end(); ++it)
1256 from->sendNotice((*it).first);
1258 from->sendNotice("\002End of spy list.\002");
1262 UserCommands::SpyMessage(ServerConnection *cnx, Person *from,
1263 String channel, String rest)
1265 String nick = from->getNick();
1267 if (cnx->bot->spyList.find(nick) != cnx->bot->spyList.end()) {
1268 from->sendNotice("\002You are already spying messages.\002");
1272 Person *f = from->copy();
1274 cnx->bot->spyList[nick.toLower()] = f;
1275 from->sendNotice("\002You have been added to the spy list.\002");
1280 UserCommands::Reconnect(ServerConnection *cnx, Person *from,
1281 String channel, String rest)
1283 String nick = from->getNick();
1285 if (cnx->bot->canChangeServer()) {
1286 cnx->queue->sendQuit("Reconnecting");
1287 cnx->bot->reconnect();
1290 from->sendNotice("\002I can not change server without losing op on a channel I am on.\002");
1294 UserCommands::RSpyMessage(ServerConnection *cnx, Person *from,
1295 String channel, String rest)
1297 String nick = from->getNick().toLower();
1299 if (cnx->bot->spyList.find(nick) == cnx->bot->spyList.end()) {
1300 from->sendNotice("\002You are not in the spy list.\002");
1304 delete cnx->bot->spyList[nick];
1305 cnx->bot->spyList.erase(nick);
1306 from->sendNotice("\002You have been removed from the "
1312 UserCommands::Unlock(ServerConnection *cnx, Person *from,
1313 String channel, String rest)
1315 cnx->bot->channelList->getChannel(channel)->lockedTopic = false;
1316 from->sendNotice(String("\002Unlocking topic for channel\002 ") +
1321 UserCommands::Stats(ServerConnection *cnx, Person *from,
1322 String channel, String rest)
1324 String nick = from->getNick();
1326 from->sendNotice(String("\002Keeping modes\002 ") +
1327 cnx->bot->channelList->getChannel(channel)->keepModes + " \002on channel\002 " +
1333 UserCommands::TBan(ServerConnection *cnx, Person *from,
1334 String channel, String rest)
1336 Channel * c = cnx->bot->channelList->getChannel(channel);
1338 StringTokenizer st(rest);
1339 String who = st.next_token();
1340 String t = st.next_token();
1343 if (who == "" || t == "") {
1345 from->sendNotice("\002Invalid syntax for this command.\002");
1349 if (Utils::wildcard_p(who) && from) {
1350 User * u = c->getUser(from->getNick());
1351 if (u && u->getLevel() < User::TRUSTED_USER) {
1353 from->sendNotice("\002You need an higher level to use"
1359 if (!cnx->bot->iAmOp(channel)) {
1361 from->sendNotice(String("\002I am not channel op on\002 ") +
1366 if (!Utils::wildcard_p(who))
1367 dest = cnx->bot->getUserhost(channel, who);
1373 from->sendNotice(String("\002I can not find\002 ") + who);
1379 if ((w = Utils::str2time(t)) == 0) {
1381 from->sendNotice(t + " \002is an invalid time.\002");
1385 dest = Utils::make_wildcard(dest);
1388 for (std::list<UserListItem *>::iterator it = cnx->bot->userList->l.begin();
1389 it != cnx->bot->userList->l.end();
1391 if (m.matches((*it)->mask) &&
1392 (*it)->channelMask.matches(channel) &&
1393 (*it)->prot >= User::NO_BAN) {
1395 from->sendNotice(String("\002I can not ban\002 ") +
1396 who + " \002on channel\002 " +
1397 channel + " \002(protection).\002");
1401 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
1402 it != c->channelBanlist.end(); ++it)
1403 if (m.matches((*it)->getMask()))
1404 cnx->queue->sendChannelMode(channel, "-b", (*it)->getMask().getMask());
1406 cnx->bot->channelList->getChannel(channel)->addBan(dest, w);
1407 cnx->queue->sendChannelMode(channel, "+b", dest);
1408 cnx->bot->todoList->addDeban(channel, dest, (time_t)w);
1413 UserCommands::TKBan(ServerConnection *cnx, Person *from,
1414 String channel, String rest)
1416 StringTokenizer st(rest);
1417 String who = st.next_token();
1418 String t = st.next_token();
1420 TBan(cnx, 0, channel, who + " " + t);
1421 Kick(cnx, from, channel, who + " " + st.rest());
1426 UserCommands::Topic(ServerConnection *cnx, Person *from,
1427 String channel, String rest)
1429 String nick = from->getNick();
1431 if (rest.length() == 0) {
1432 if (cnx->bot->channelList->getChannel(channel)->channelTopic == "")
1433 from->sendNotice(String("\002No topic is set for channel\002 ") +
1434 channel + "\002.\002");
1436 from->sendNotice(String("\002Topic for\002 ") +
1437 channel + " \002is:\002 " +
1438 cnx->bot->channelList->getChannel(channel)->channelTopic);
1440 if (cnx->bot->channelList->getChannel(channel)->lockedTopic)
1441 from->sendNotice(String("\002Topic is locked on channel\002 ") +
1444 cnx->queue->sendTopic(channel, rest);
1449 UserCommands::UserList(ServerConnection *cnx, Person *from,
1450 String channel, String rest)
1452 from->sendNotice("\002Userlist:\002");
1453 from->sendNotice("\002Mask Channel Level Prot Aop Expires\002");
1455 for (std::list<UserListItem *>::iterator it = cnx->bot->userList->l.begin();
1456 it != cnx->bot->userList->l.end();
1458 from->sendNotice((*it)->mask.getMask().pad(25)
1460 + (*it)->channelMask.getMask().pad(10)
1462 String(Utils::level2str((*it)->level)).pad(12)
1464 String(Utils::prot2str((*it)->prot)).pad(7)
1466 String(Utils::bool2str((*it)->aop)).pad(5)
1468 String(Utils::long2str ((*it)->expirationDate)));
1470 from->sendNotice("\002End of userlist.\002");
1474 UserCommands::Who(ServerConnection *cnx, Person *from,
1475 String channel, String rest)
1477 String nick = from->getNick();
1478 User * u = cnx->bot->channelList->getChannel(channel)->getUser(nick);
1482 uli = u->userListItem;
1484 uli = cnx->bot->userList->getUserListItem(from->getAddress(),
1488 from->sendNotice(String("\002You are\002 ") +
1489 uli->mask.getMask() + " \002on\002 " +
1490 uli->channelMask.getMask());
1491 from->sendNotice(String("\002Lvl:\002 ") +
1492 Utils::level2str(uli->level) +
1494 Utils::prot2str(uli->prot) +
1496 Utils::bool2str(uli->aop) +
1497 " \002Expired:\002 " +
1498 Utils::bool2str(!uli->isStillValid()) +
1499 " \002Ident:\002 " +
1500 (uli && !uli->identified ? "\026" : "") +
1501 Utils::bool2str(uli && uli->identified) +
1502 (uli && !uli->identified ? "\026" : ""));
1504 from->sendNotice(String("\002You are not in the userlist for\002 ") +
1509 UserCommands::Whois(ServerConnection *cnx, Person *from,
1510 String channel, String rest)
1512 String nick = from->getNick();
1514 if (!rest.length()) {
1515 from->sendNotice("\002No nick specified.\002");
1519 StringTokenizer st(rest);
1520 String otherNick = st.next_token();
1522 User * u = cnx->bot->channelList->getChannel(channel)->getUser(otherNick);
1526 uli = u->userListItem;
1528 uli = cnx->bot->userList->getUserListItem(otherNick + "!" +
1529 cnx->bot->getUserhost(channel,
1534 from->sendNotice(otherNick +
1535 " \002is\002 " + uli->mask.getMask() +
1536 " \002on\002 " + uli->channelMask.getMask());
1537 from->sendNotice(String("\002Lvl:\002 ") +
1538 Utils::level2str(uli->level) +
1540 Utils::prot2str(uli->prot) +
1542 Utils::bool2str(uli->aop) +
1543 " \002Expired:\002 " +
1544 Utils::bool2str(!uli->isStillValid()) +
1545 " \002Ident:\002 " +
1546 Utils::bool2str(uli && uli->identified));
1548 from->sendNotice(otherNick +
1549 " \002is not in the userlist for\002 " +