[project @ 2002-08-18 21:34:24 by unknown_lamer]
[clinton/bobotpp.git] / source / UserCommands.C
CommitLineData
cb21075d 1// UserCommands.C -*- C++ -*-
2// Copyright (c) 1997, 1998 Etienne BERNARD
3// Copyright (C) 2002 Clinton Ebadi
4
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
8// any later version.
9
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.
14
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <fstream>
e07b6b46 24#include <map>
cb21075d 25#include <sys/types.h>
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
29#include <netdb.h>
30#include <ctype.h>
31#ifndef _X_OPEN_SOURCE
32#define _X_OPEN_SOURCE
33#endif
34#ifndef _X_OPEN_SOURCE_EXTENDED
35#define _X_OPEN_SOURCE_EXTENDED 1
36#endif
37#ifndef __USE_XOPEN
38#define __USE_XOPEN
39#endif
40#include <unistd.h>
41
42#include "Commands.H"
43#include "UserCommands.H"
44#include "DCCConnection.H"
6530edbf 45#include "DCCManager.H"
cb21075d 46#include "Parser.H"
47#include "Macros.H"
48#include "StringTokenizer.H"
49#include "Utils.H"
50#include "ServerList.H"
51#include "Server.H"
52
53#ifdef NOCRYPT
54char * crypt(const char *p, const char *s) { return p; }
55#endif
56
57void
58UserCommands::Action(ServerConnection *cnx, Person *from,
59 String channel, String rest)
60{
61 Message m = Commands::Action(cnx->bot, channel, rest);
62 if (m.getCode() != 0)
63 from->sendNotice(m.getMessage());
64}
65
66void
67UserCommands::AddUser(ServerConnection *cnx, Person *from,
68 String channel, String rest)
69{
70 StringTokenizer st(rest);
71 String mask, who, maskChannel, level, prot,
72 aop, expiration, passwd;
73
74 mask = who = st.nextToken();
75 maskChannel = st.nextToken();
76 level = st.nextToken();
77 prot = st.nextToken();
78 aop = st.nextToken();
79 expiration = st.nextToken();
80 passwd = st.nextToken();
81
82 if (mask == "" || maskChannel == "" || level == "" ||
83 prot == "" || aop == "") {
84 from->sendNotice("\002Invalid syntax for this command.\002");
85 return;
86 }
87
88// if (!Utils::isWildcard(mask)) {
89// mask = cnx->bot->getUserhost(channel, who);
90// if (mask == "") {
91// from->sendNotice(String("\002I can not find\002 ") + who);
92// return;
93// }
94// mask = Utils::makeWildcard(mask);
95// }
96
97// if (cnx->bot->userList->isInUserList(mask, maskChannel)) {
98// from->sendNotice(who + " \002is already in userlist on channel(s)\002 " +
99// maskChannel);
100// return;
101// }
102
103 int l, p;
104 bool a;
105 time_t e;
106
107 l = atoi((const char *)level);
108 if (l < 0 || l > User::FRIEND)
109 return;
110 if (l > Utils::getLevel(cnx->bot, from->getAddress())) {
111 from->sendNotice("\002You can not give a level greater than yours.\002");
112 return;
113 }
114 p = atoi((const char *)prot);
115 if (p < 0 || p > User::NO_DEOP)
116 return;
117 a = (bool)atoi((const char *)aop);
118 if (a != 0 && a != 1)
119 return;
120
121 e = Utils::strToTime(expiration);
122
123 if (!e)
124 e = -1;
125
126 // cnx->bot->userList->addUser(mask, maskChannel, l, p, a, e, passwd);
127
128 Message m =
129 Commands::AddUser (cnx->bot, who, maskChannel, l, p, a, e, passwd);
130 if (!m.getCode ())
131 {
132 from->sendNotice(String("\002Added\002 ") + mask +
133 " \002on channels\002 " + maskChannel);
134 from->sendNotice(String("\002Level:\002 ") +
135 Utils::levelToStr(l) +
136 " \002Protection:\002 " +
137 Utils::protToStr(p) +
138 " \002Auto-op:\002 " +
139 Utils::boolToStr(a));
140 }
141 else
142 from->sendNotice(m.getMessage ());
143
144 // cnx->bot->rehash();
145}
146
147void
148UserCommands::AddServer(ServerConnection *cnx, Person *from,
149 String channel, String rest)
150{
151 if (rest.length() == 0) {
152 from->sendNotice("\002You must supply a server name.\002");
153 return;
154 }
155
156 StringTokenizer st(rest);
157 String serverName = st.nextToken();
158 int port = 6667;
159
160 if (st.hasMoreTokens()) {
161 String temp = st.nextToken();
162 port = atoi((const char *)temp);
163 }
164
165 Message m = Commands::AddServer(cnx->bot, serverName, port);
166 if (m.getCode() != 0)
167 from->sendNotice(m.getMessage());
168 else
169 from->sendNotice(String("\002Server\002 ") +
170 serverName + " \002on port\002 " +
171 String((long)port) + " \002has been added "
172 "to the server list.\002");
173}
174
175// FIXME: does this work now
176void
177UserCommands::AddShit(ServerConnection *cnx, Person *from,
178 String channel, String rest)
179{
180 StringTokenizer st(rest);
181 String mask, who, maskChannel, level, expiration, reason;
182
183 mask = who = st.nextToken();
184 maskChannel = st.nextToken();
185 level = st.nextToken();
186 expiration = st.nextToken();
187 reason = st.rest().trim();
188
189 /* if (mask == "" || maskChannel == "" || level == "") {
190 from->sendNotice("\002Invalid syntax for this command.\002");
191 return;
192 }
193 */
194
195 /*
196 if (reason == "")
197 reason = "You're on my shitlist, lamer";
198 */
199
200 /*
201 if (!Utils::isWildcard(mask)) {
202 mask = cnx->bot->getUserhost(channel, who);
203 if (mask == "") {
204 from->sendNotice(String("\002I can not find\002 ") + who);
205 return;
206 }
207 mask = Utils::makeWildcard(mask);
208 if (cnx->bot->shitList->getShit(mask, maskChannel)) {
209 from->sendNotice(mask + " \002is already in shitlist on channel(s)\002 " +
210 maskChannel);
211 return;
212 }
213 }
214 */
215 int l;
216 time_t e;
217
218 l = atoi((const char *)level);
219 if (l < 0 || l > ShitEntry::SHIT_NODEBAN)
220 return;
221
222 e = Utils::strToTime(expiration);
223
224 if (!e)
225 e = -1;
226
227 /*
228 if (cnx->bot->userList->getMaxProt(mask, maskChannel) > 0) {
229 from->sendNotice(String("\002I can not add\002 ") + who +
230 " \002into the shitlist (protection).");
231 return;
232 }
233
234 cnx->bot->shitList->addShit(mask, maskChannel, l, e, reason);
235 */
236
237 Message M = Commands::AddShit (cnx->bot, mask, maskChannel, l, e, reason);
238 if (!M.getCode ())
239 from->sendNotice(String("\002Added\002 ") + mask +
240 " \002on channels\002 " + maskChannel +
241 " \002into the shitlist.\002");
242 else
243 from->sendNotice (M.getMessage ());
244}
245
246// FIXME: Convert (and change ?)
247void
248UserCommands::Alias(ServerConnection *cnx, Person *from,
249 String channel, String rest)
250{
251 StringTokenizer st(rest);
252 String newF = st.nextToken().toUpper();
253 String oldF = st.nextToken().toUpper();
cb21075d 254
255 if (newF == "" || oldF == "") {
256 from->sendNotice("\002Invalid syntax for this command.\002");
257 return;
258 }
259
260 // First, we check that the "new" function does not exist
e07b6b46 261 if (cnx->bot->userFunctions[newF]) {
cb21075d 262 from->sendNotice(newF + " \002is already an alias.\002");
263 return;
e07b6b46 264 }
cb21075d 265
266 // Next, we check that the "old" function exist
e07b6b46 267 if (!cnx->bot->userFunctions[oldF])
268 {
269 from->sendNotice(String("\002I don't know the\002 ") + oldF +
270 " \002command.");
271 return;
cb21075d 272 }
cb21075d 273
274 // Fine, we do the binding
e07b6b46 275 cnx->bot->userFunctions[newF] =
276 new userFunction (*cnx->bot->userFunctions[oldF]);
cb21075d 277
278 from->sendNotice("\002Alias added.\002");
279}
280
281void
282UserCommands::Ban(ServerConnection *cnx, Person *from,
283 String channel, String rest)
284{
285 if (rest.length() == 0) {
286 if (from)
287 from->sendNotice("\002No nick/mask specified.\002");
288 return;
289 }
290
291 Message m = Commands::Ban(cnx->bot, channel, rest);
292 if (m.getCode() != 0 && from)
293 from->sendNotice(m.getMessage());
294}
295
296void
297UserCommands::BanList(ServerConnection *cnx, Person *from,
298 String channel, String rest)
299{
300 time_t current = time(0);
301 Channel *c = cnx->bot->channelList->getChannel(channel);
302 from->sendNotice(String("\002Banlist for channel\002 ") +
303 channel + "\002:\002");
304 from->sendNotice("\002Mask Expires (seconds)\002");
305 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
306 it != c->channelBanlist.end(); ++it)
307 if ((*it)->getExpirationDate() == -1)
308 from->sendNotice((*it)->getMask().pad(30) + " -1");
309 else
310 from->sendNotice((*it)->getMask().pad(30) + " " +
311 String((long)((*it)->getExpirationDate()-current)));
312 from->sendNotice("\002End of banlist.\002");
313}
314
315// void
316// UserCommands::ChangeLevel(ServerConnection *cnx, Person *from,
317// String channel, String rest)
318// {
319// StringTokenizer st(rest);
320
321// String who;
322// String mask = who = st.nextToken();
323// String maskChannel = st.nextToken();
324// String level = st.nextToken();
325
326// if (mask == "" || maskChannel == "" || level == "") {
327// from->sendNotice("\002Invalid syntax for this command.\002");
328// return;
329// }
330
331// if (!Utils::isWildcard(mask)) {
332// mask = cnx->bot->getUserhost(channel, who);
333// if (mask == "") {
334// from->sendNotice(String("\002I can not find\002 ") + who);
335// return;
336// }
337// mask = from->getNick() + "!" + mask;
338// }
339
340// UserListItem *uli = cnx->bot->userList->getUserListItem(mask, maskChannel);
341
342// if (!uli) {
343// from->sendNotice(String("\002I can not find\002 ") + who +
344// " \002on channel(s)\002 " + maskChannel +
345// " \002in my userlist.\002");
346// return;
347// }
348
349// int l = atoi((const char *)level);
350
351// if (l < User::NONE || l > User::MASTER) {
352// from->sendNotice("\002This is not a valid level.\002");
353// return;
354// }
355
356// if (l > Utils::getLevel(cnx->bot, from->getAddress())) {
357// from->sendNotice("\002You can not give a level greater than yours.\002");
358// return;
359// }
360
361// if (Utils::getLevel(cnx->bot, from->getAddress()) < uli->level) {
362// from->sendNotice("\002You can not change the level for a person "
363// "whose level is greater than yours.\002");
364// return;
365// }
366
367// uli->level = l;
368// from->sendNotice("\002Level changed.\002");
369// cnx->bot->rehash();
370// }
371
372void
373UserCommands::Channels(ServerConnection *cnx, Person *from,
374 String channel, String rest)
375{
376 String result = "";
377
378 for (std::map<String, Channel *, std::less<String> >::iterator it =
379 cnx->bot->channelList->begin();
380 it != cnx->bot->channelList->end(); ++it)
381 result = result + (*it).first + " ";
382
383 if (result == "")
384 from->sendNotice("\002I am not on any channel.\002");
385 else
386 from->sendNotice(String("\002I am currently on channel(s):\002 ") +
387 + result);
388}
389
390void
391UserCommands::Cycle(ServerConnection *cnx, Person *from,
392 String channel, String rest)
393{
394 Message m = Commands::Cycle(cnx->bot, channel);
395 if (m.getCode() != 0)
396 from->sendNotice(m.getMessage());
397}
398
399void
400UserCommands::DCCList(ServerConnection *cnx, Person *from,
401 String channel, String rest)
402{
403 time_t current_time = time(0);
404
405 from->sendNotice("\002DCClist:\002");
406 from->sendNotice("\002Hostname Last used\002");
407
6530edbf 408 for (DCC_MAP::iterator it =
409 cnx->bot->dccConnections->MAP()->begin ();
410 it != cnx->bot->dccConnections->MAP()->end();
cb21075d 411 ++it) {
6530edbf 412 from->sendNotice(String(it->second->DCC()->nuh).pad(32) + " " +
cb21075d 413 String((long)(current_time -
6530edbf 414 it->second->DCC()->lastSpoken)));
cb21075d 415 }
416
417 from->sendNotice("\002End of dcclist.\002");
418}
419
420void
421UserCommands::Deban(ServerConnection *cnx, Person *from,
422 String channel, String rest)
423{
424 if (rest.length() == 0) {
425 from->sendNotice("\002No nick/mask specified.\002");
426 return;
427 }
428
429 Message m = Commands::Deban(cnx->bot, channel, rest);
430 if (m.getCode() != 0)
431 from->sendNotice(m.getMessage());
432}
433
434void
435UserCommands::DelServer(ServerConnection *cnx, Person *from,
436 String channel, String rest)
437{
438 if (rest.length() == 0) {
439 from->sendNotice("\002You need to supply a server number"
440 " for this command.\002");
441 return;
442 }
443
444 int serverNumber = atoi(rest);
445
446 Message m = Commands::DelServer(cnx->bot, serverNumber);
447 if (m.getCode() != 0)
448 from->sendNotice(m.getMessage());
449 else
450 from->sendNotice(String("Deleted server ") +
451 cnx->bot->serverList->get(serverNumber)->getHostName() +
452 " (" + String((long)cnx->bot->serverList->get(serverNumber)->getPort()) +
453 ").");
454}
455
456// FIXME: Convert
457void
458UserCommands::DelUser(ServerConnection *cnx, Person *from,
459 String channel, String rest)
460{
461 StringTokenizer st(rest);
462
463 String who;
464 String mask = who = st.nextToken();
465 String maskChannel = st.nextToken();
466
467 if (mask == "" || maskChannel == "") {
468 from->sendNotice("\002Invalid syntax for this command.\002");
469 return;
470 }
471
472 if (!Utils::isWildcard(mask)) {
473 mask = cnx->bot->getUserhost(channel, who);
474 if (mask == "") {
475 from->sendNotice(String("\002I can not find\002 ") + who);
476 return;
477 }
478 mask = Utils::makeWildcard(mask);
479 }
480
481 if (!cnx->bot->userList->isInUserList(mask, maskChannel)) {
482 from->sendNotice(mask + " \002is not in userlist on channel(s)\002 " +
483 maskChannel);
484 return;
485 }
486
487 cnx->bot->userList->removeUser(mask, maskChannel);
488 from->sendNotice(who + " \002has been removed from the userlist.\002");
489 cnx->bot->rehash();
490}
491
492// FIXME: Convert
493void
494UserCommands::DelShit(ServerConnection *cnx, Person *from,
495 String channel, String rest)
496{
497 StringTokenizer st(rest);
498
499 String who;
500 String mask = who = st.nextToken();
501 String maskChannel = st.nextToken();
502
503 if (mask == "" || maskChannel == "") {
504 from->sendNotice("\002Invalid syntax for this command.\002");
505 return;
506 }
507
508 if (!Utils::isWildcard(mask)) {
509 mask = cnx->bot->getUserhost(channel, who);
510 if (mask == "") {
511 from->sendNotice(String("\002I can not find\002 ") + who);
512 return;
513 }
514 mask = Utils::makeWildcard(mask);
515 }
516
517 if (!cnx->bot->shitList->getShit(mask, maskChannel)) {
518 from->sendNotice(mask + " \002is not in shitlist on channel(s)\002 " +
519 maskChannel);
520 return;
521 }
522
523 cnx->bot->shitList->delShit(mask, maskChannel);
524 from->sendNotice(who + " \002has been removed from the shitlist.\002");
525}
526
527void
528UserCommands::Deop(ServerConnection *cnx, Person *from,
529 String channel, String rest)
530{
531 String target = rest;
532
533 if (target.length() == 0)
534 target = from->getNick();
535
536 Message m = Commands::Deop(cnx->bot, channel, target);
537 if (m.getCode() != 0)
538 from->sendNotice(m.getMessage());
539}
540
541void
542UserCommands::Die(ServerConnection *cnx, Person *from,
543 String channel, String rest)
544{
545 String reason;
546
547 if (rest.length() == 0)
548 reason = "Leaving";
549 else
550 reason = rest;
551
552 Commands::Die(cnx->bot, reason);
553}
554
555void
556UserCommands::Do(ServerConnection *cnx, Person *from,
557 String channel, String rest)
558{
559 if (rest.length() != 0)
560 Commands::Do(cnx->bot, rest);
561}
562
563#ifdef USESCRIPTS
564void
565UserCommands::Execute(ServerConnection *cnx, Person *from,
566 String channel, String rest)
567{
568 if (rest.length() != 0)
569 Interp::Execute(cnx->bot, rest);
570}
571#endif
572
573void
574UserCommands::Help(ServerConnection *cnx, Person *from,
575 String channel, String rest)
576{
577 if (rest.length() == 0) {
578 from->sendNotice("\002Available topics for you are:\002");
579 int level = Utils::getLevel(cnx->bot, from->getAddress());
580 String result = "";
581 int length = 0;
e07b6b46 582 std::map<std::string, class userFunction*, std::less<std::string> >::iterator it;
cb21075d 583 for (it = cnx->bot->userFunctions.begin(); it != cnx->bot->userFunctions.end(); ++it)
e07b6b46 584 if ((*it).second->minLevel <= level) {
585 result = result + (*it).first + " ";
586 length += (*it).first.length() + 1;
cb21075d 587 if (length >= 256) {
588 from->sendNotice(result);
589 result = ""; length = 0;
590 }
591 }
592 if (result != "")
593 from->sendNotice(result);
594 from->sendNotice("\002Use\002 HELP <command> \002for"
595 " help about\002 <command>");
596 return;
597 }
598
599 StringTokenizer st(rest);
600 String command = st.nextToken().toUpper();
601 std::ifstream helpFile(cnx->bot->helpFileName);
602
603 if (!helpFile) {
604 from->sendNotice(String("\002Error: I can not find the "
605 "help file\002 ") +
606 cnx->bot->helpFileName);
607 return;
608 }
609
610 String buf;
611 while (!helpFile.eof()) {
612 helpFile >> buf;
613 if (buf.subString(0, command.length()) == String(":") + command) {
614 buf = buf.subString(1);
615 from->sendNotice(String("\002Help for\002 ") + command +
616 "\002:\002");
617 while (buf != "") {
618 from->sendNotice(buf);
619 helpFile >> buf;
620 }
621 from->sendNotice("\002End of help.\002");
622 return;
623 }
624 }
625
626 from->sendNotice(String("\002No such topic (\002") +
627 command + "\002).\002");
628}
629
630void
631UserCommands::Ident(ServerConnection *cnx, Person *from,
632 String channel, String rest)
633{
634 Channel *c = cnx->bot->channelList->getChannel(channel);
635
636 if (rest.length() <= 2) {
637 from->sendNotice("\002No password specified or password "
638 "too short.\002");
639 return;
640 }
641
642 User * u = c->getUser(from->getNick());
643 if (!u) {
644 from->sendNotice(String("\002You can identify yourself on"
645 " channel\002 ") + channel +
646 " \002only if you are on the channel.\002");
647 return;
648 }
649
650 if (u->userListItem && u->userListItem->identified) {
651 from->sendNotice(String("\002You are already identified on"
652 " channel\002 ") + channel);
653 return;
654 }
655
656 if (!u->userListItem) {
657 from->sendNotice("\002You are not in my userlist.\002");
658 return;
659 }
660
661 if (u->userListItem->passwd ==
662 crypt((const char *)rest, (const char *)u->userListItem->passwd)) {
663 // For each channel, we increment identification counter
664 for (std::map<String, Channel *, std::less<String> >::iterator it =
665 cnx->bot->channelList->begin();
666 it != cnx->bot->channelList->end(); ++it)
667 u->userListItem->identified++;
668
669 from->sendNotice("\002You are now identified.\002");
670 } else
671 from->sendNotice("\002This is a wrong password.\002");
672}
673
674void
675UserCommands::Invite(ServerConnection *cnx, Person *from,
676 String channel, String rest)
677{
678 Message m = Commands::Invite(cnx->bot, channel, rest);
679 if (m.getCode() < 0)
680 from->sendNotice(m.getMessage());
681 from->sendNotice(String("\002Inviting\002 ") + rest + " \002on channel\002 " + channel);
682}
683
684// FIXME: Convert
685void
686UserCommands::Join(ServerConnection *cnx, Person *from,
687 String channel, String rest)
688{
689 StringTokenizer st(rest);
690 channel = st.nextToken();
691
692 if (!Utils::isValidChannelName(channel)) {
693 from->sendNotice(String("\002") + channel +
694 " is not a valid channel name\002");
695 return;
696 }
697
698 // We change the key only if we are not on the channel. We don't trust
699 // the user...
700 if (!cnx->bot->channelList->getChannel(channel)) {
701 if (cnx->bot->wantedChannels[channel])
702 cnx->bot->wantedChannels[channel]->key = st.rest();
703 else {
704 cnx->bot->wantedChannels[channel] = new wantedChannel("", "", st.rest());
705 }
706 }
707 cnx->queue->sendJoin(channel, cnx->bot->wantedChannels[channel]->key);
708}
709
710// FIXME: Convert
711void
712UserCommands::Keep(ServerConnection *cnx, Person *from,
713 String channel, String rest)
714{
715 String nick = from->getNick();
716
717 if (rest.length() == 0) {
718 from->sendNotice("\002No channel modes specified.\002");
719 return;
720 }
721
722 cnx->bot->channelList->getChannel(channel)->keepModes = rest;
723 from->sendNotice(String("\002Keeping modes\002 ") +
724 rest + " \002on channel\002 " +
725 channel);
726}
727
728// FIXME: Convert
729void
730UserCommands::Kick(ServerConnection *cnx, Person *from,
731 String channel, String rest)
732{
733 String nick = from->getNick();
734
735 Channel * c = cnx->bot->channelList->getChannel(channel);
736
737 if (rest.length() == 0) {
738 from->sendNotice("\002No nick specified.\002");
739 return;
740 }
741
742 StringTokenizer st(rest);
743 String who = st.nextToken();
744
745 if (Utils::isWildcard(who)) {
746 User * u = c->getUser(nick);
747 if (!u)
748 return;
749 if (u->getLevel() < User::TRUSTED_USER) {
750 from->sendNotice("\002You need an higher level to "
751 "use wildcards.\002");
752 return;
753 }
754 }
755
756 if (!cnx->bot->iAmOp(channel)) {
757 from->sendNotice(String("\002I am not channel op on\002 ") +
758 channel);
759 return;
760 }
761
762 if (Utils::isWildcard(who)) {
763 Mask m(who);
764 for (std::map<String, User *, std::less<String> >::iterator it =
765 c->channelMemory.begin();
766 it != c->channelMemory.end();
767 ++it)
768 if (m.matches((*it).second->nick + "!" +
769 (*it).second->userhost) &&
770 (*it).second->getProt() < User::NO_KICK)
771 cnx->queue->sendKick(channel, (*it).second->nick, st.rest());
772 } else {
773 User * u = c->getUser(who);
774 if (!u) {
775 from->sendNotice(String("\002I can not find\002 ") +
776 who + " \002on\002 " + channel);
777 return;
778 }
779 if (u->getProt() < User::NO_KICK)
780 cnx->queue->sendKick(channel, who, st.rest());
781 else
782 from->sendNotice(String("\002I can not kick\002 ") +
783 who + " \002on\002 " + channel +
784 " \002(protected).\002");
785 }
786}
787
788// FIXME: Convert
789void
790UserCommands::KickBan(ServerConnection *cnx, Person *from,
791 String channel, String rest)
792{
793 StringTokenizer st(rest);
794
795 Ban(cnx, 0, channel, st.nextToken());
796 Kick(cnx, from, channel, rest);
797}
798
799void
800UserCommands::Load(ServerConnection *cnx, Person *from,
801 String channel, String rest)
802{
803 cnx->bot->shitList->read();
804 cnx->bot->userList->read();
805 cnx->bot->userList->addUserFirst(cnx->bot->nickName + "!" + cnx->bot->userHost, "*", 0, 3, true, -1, "");
806 cnx->bot->rehash();
807 from->sendNotice("\002Userlist and shitlist loaded.\002");
808}
809
810#ifdef USESCRIPTS
811void
812UserCommands::LoadScript(ServerConnection *cnx, Person *from,
813 String channel, String rest)
814{
815 if (rest.length() != 0)
816 Interp::LoadScript(cnx->bot, rest);
817}
818#endif
819
820// FIXME: Convert
821void
822UserCommands::Lock(ServerConnection *cnx, Person *from,
823 String channel, String rest)
824{
825 cnx->bot->channelList->getChannel(channel)->lockedTopic = true;
826 from->sendNotice(String("\002Locking topic for channel\002 ") +
827 channel);
828}
829
830// FIXME: Convert
831void
832UserCommands::Mode(ServerConnection *cnx, Person *from,
833 String channel, String rest)
834{
835 String nick = from->getNick();
836
837 if (rest.length() == 0) {
838 from->sendNotice("\002I need a parameter for this command.\002");
839 return;
840 }
841
842 if (!cnx->bot->iAmOp(channel)) {
843 from->sendNotice(String("\002I am not channel op on\002 ") +
844 channel);
845 return;
846 }
847
848 cnx->queue->sendChannelMode(String("MODE ") + channel + " " + rest);
849}
850
851void
852UserCommands::Msg(ServerConnection *cnx, Person *from,
853 String channel, String rest)
854{
855 StringTokenizer st(rest);
856 String who = st.nextToken();
857 String message = st.rest();
858
859 Message m = Commands::Msg(cnx->bot, who, message);
860 if (m.getCode() != 0)
861 from->sendNotice(m.getMessage());
862}
863
864void
865UserCommands::Names(ServerConnection *cnx, Person *from,
866 String channel, String rest)
867{
868 String nick = from->getNick();
869 String result = "";
870 int length = 0;
871 Channel *c = cnx->bot->channelList->getChannel(channel);
872 std::map<String, User *, std::less<String> >::iterator it;
873
874 from->sendNotice(String("\002Names on ") +
875 channel + ":\002");
876
877 for (it = c->channelMemory.begin();
878 it != c->channelMemory.end(); ++it) {
879 result = result +
880 ((*it).second->mode & User::OP_MODE ? "@" :
881 ((*it).second->mode & User::VOICE_MODE ? "+" : "")) +
882 (*it).second->nick + " ";
883 length += (*it).first.length() + 1;
884 if (length >= 256) {
885 from->sendNotice(result);
886 result = ""; length = 0;
887 }
888 }
889
890 if (result != "")
891 from->sendNotice(result);
892
893 from->sendNotice("\002End of names.\002");
894}
895
896// FIXME: Convert
897void
898UserCommands::NextServer(ServerConnection *cnx, Person *from,
899 String channel, String rest)
900{
901 if (cnx->bot->serverList->size() == 0) {
902 from->sendNotice("\002Server list is empty !\002");
903 return;
904 }
905
906 if (cnx->bot->serverList->size() == 1) {
907 from->sendNotice("\002Server list has only one item. Use"
908 " \"reconnect\" to force reconnection.\002");
909 return;
910 }
911
912 if (cnx->bot->canChangeServer()) {
913 cnx->queue->sendQuit("Changing server");
914 cnx->bot->nextServer();
915 }
916 else
917 from->sendNotice("\002I can not change server without"
918 " losing op on a channel I am on.\002");
919}
920
921// FIXME: Convert
922void
923UserCommands::Nick(ServerConnection *cnx, Person *from,
924 String channel, String rest)
925{
926 // We parse the parameters
927 StringTokenizer st(rest);
928 String nick = st.nextToken();
929
930 if (rest == "") {
931 from->sendNotice(String("\002No nickname given.\002"));
932 return;
933 }
934
935 if (!Utils::isValidNickName(nick)) {
936 from->sendNotice(String("\002") + nick +
937 " is not a valid nickname\002");
938 return;
939 }
940
941 cnx->bot->wantedNickName = nick;
942 cnx->queue->sendNick(nick);
943}
944
945void
946UserCommands::NsLookup(ServerConnection *cnx, Person *from,
947 String channel, String rest)
948{
949 String target;
950
951 if (rest.length() == 0) {
952 from->sendNotice("\002You need to supply a nick or an "
953 "host for this command.\002");
954 return;
955 }
956
957 if (rest.find('.') == -1) {
958 StringTokenizer st(cnx->bot->getUserhost("", rest));
959 st.nextToken('@');
960 target = st.rest();
961 if (target.length() == 0) {
962 from->sendNotice(String("\002I could not find\002 ") +
963 target);
964 return;
965 }
966 } else
967 target = rest;
968
969 struct hostent * host;
970 struct in_addr iaddr;
971
972 if (isdigit(target[0])) { // An IP ?
973 iaddr.s_addr = inet_addr((const char *)target);
974 host = gethostbyaddr((char *)(&iaddr),
975 sizeof(struct in_addr),
976 AF_INET);
977 if (host) {
978 from->sendNotice(target +
979 " \002is the IP address of\002 " +
980 host->h_name);
981 return;
982 }
983 } else {
984 host = gethostbyname((const char *)target);
985 if (host) {
986 memcpy((char *)&iaddr, (char *)host->h_addr,
987 host->h_length);
988 from->sendNotice(target + " \002has\002 " +
989 inet_ntoa(iaddr) + " \002for IP address.\002");
990 return;
991 }
992 }
993
994 from->sendNotice(String("\002I could not find host\002 ") +
995 target);
996}
997
998// FIXME: Convert
999void
1000UserCommands::Op(ServerConnection *cnx, Person *from,
1001 String channel, String rest)
1002{
1003 String nick = from->getNick();
1004
1005 if (!cnx->bot->iAmOp(channel)) {
1006 from->sendNotice(String("\002I am not channel op on\002 ") +
1007 channel);
1008 return;
1009 }
1010
1011 if (Utils::isWildcard(rest)) {
1012 from->sendNotice("\002Mass op is not allowed.\002");
1013 return;
1014 }
1015
1016 String target;
1017
1018 if (rest.length() == 0)
1019 target = nick;
1020 else
1021 target = rest;
1022
1023 User *u = cnx->bot->channelList->getChannel(channel)->getUser(target);
1024 if (!u) {
1025 from->sendNotice(String("\002I cannot find\002 ") + target + " \002on channel\002 " + channel);
1026 return;
1027 }
1028
1029 ShitEntry *se = cnx->bot->shitList->getShit(target, channel);
1030 if (se && se->isStillValid() && se->getShitLevel() >= ShitEntry::SHIT_NOOP) {
1031 from->sendNotice(String("\002I can not op\002 ")+target+" \002on channel\002 "+channel+" \002(shitlist).\002");
1032 return;
1033 }
1034
1035 if (!(u->mode & User::OP_MODE))
1036 cnx->queue->sendChannelMode(channel, "+o", target);
1037 else {
1038 if (target == nick)
1039 from->sendNotice(String("\002You are already channel "
1040 "operator on\002 ") + channel);
1041 else
1042 from->sendNotice(target + " \002is already channel "
1043 "operator on\002 " + channel);
1044 }
1045}
1046
1047// FIXME: Convert
1048void
1049UserCommands::Part(ServerConnection *cnx, Person *from,
1050 String channel, String rest)
1051{
1052 wantedChannel *w = cnx->bot->wantedChannels[channel];
1053 cnx->bot->wantedChannels.erase(channel);
1054 delete w;
1055 cnx->queue->sendPart(channel);
1056}
1057
1058void
1059UserCommands::Password(ServerConnection *cnx, Person *from,
1060 String channel, String rest)
1061{
1062 Channel *c = cnx->bot->channelList->getChannel(channel);
1063
1064 if (rest.length() == 0) {
1065 from->sendNotice("\002No password.\002");
1066 return;
1067 }
1068
1069 User * u = c->getUser(from->getNick());
1070 if (!u) {
1071 from->sendNotice(String("\002To change your password for\002") +
1072 channel + "\002, you need to be on the "
1073 "channel.\002");
1074 return;
1075 }
1076
1077 if (!u->userListItem) {
1078 from->sendNotice("\002You are not in my userlist.\002");
1079 return;
1080 }
1081
1082 if (rest.toLower() == "none") {
1083 u->userListItem->passwd = "";
1084 from->sendNotice("\002Password cleared.\002");
1085 return;
1086 }
1087
1088 static char saltChars[] = "abcdefghijklmnopqrstuvwxyz"
1089 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
1090 char salt[3];
1091 srand(time(0));
1092 salt[0] = saltChars[rand() % 64];
1093 salt[1] = saltChars[rand() % 64];
1094 salt[2] = '\0';
1095
1096 u->userListItem->passwd = crypt((const char *)rest, salt);
1097 from->sendNotice("\002Password changed.\002");
1098}
1099
1100void
1101UserCommands::Save(ServerConnection *cnx, Person *from,
1102 String channel, String rest)
1103{
1104 cnx->bot->userList->save();
1105 cnx->bot->shitList->save();
1106 from->sendNotice("\002Userlist and shitlist saved.\002");
1107}
1108
1109// FIXME: Convert
1110void
1111UserCommands::Say(ServerConnection *cnx, Person *from,
1112 String channel, String rest)
1113{
1114 if (rest.length() != 0)
1115 cnx->queue->sendPrivmsg(channel, rest);
1116}
1117
1118// FIXME: Convert
1119void
1120UserCommands::Server(ServerConnection *cnx, Person *from,
1121 String channel, String rest)
1122{
1123 int serverNumber;
1124 String nick = from->getNick();
1125
1126 if (rest.length() == 0) {
1127 from->sendNotice("\002You need to supply a server number for this command.\002");
1128 return;
1129 }
1130
1131 serverNumber = atoi(rest);
1132
1133 if (serverNumber < 0 || serverNumber >= cnx->bot->serverList->size()) {
1134 from->sendNotice(String((long)serverNumber) +
1135 " \002is an invalid server number (see the serverlist).\002");
1136 return;
1137 }
1138
1139 if (cnx->bot->canChangeServer()) {
1140 cnx->queue->sendQuit("Changing server");
1141 cnx->queue->flush();
1142 cnx->bot->connect(serverNumber);
1143 }
1144 else
1145 from->sendNotice("\002I can not change server without losing op on a channel I am on.\002");
1146}
1147
1148void
1149UserCommands::ServerList(ServerConnection *cnx, Person *from,
1150 String channel, String rest)
1151{
1152 String nick = from->getNick();
1153
1154 from->sendNotice("\002Server list:\002");
1155 long l = 0;
1156 String s;
1157 for (std::vector<class Server *>::iterator it =
1158 cnx->bot->serverList->v.begin();
1159 it != cnx->bot->serverList->v.end();
1160 ++it) {
1161 s = (*it) == cnx->server ? "\026" : "";
1162 from->sendNotice(s + String(l++) + s + " " +
1163 (*it)->getHostName() +
1164 " (" + String((long)((*it)->getPort())) +
1165 ")");
1166 }
1167 from->sendNotice("\002End of server list.\002");
1168}
1169
1170void
1171UserCommands::SetVersion(ServerConnection *cnx, Person *from,
1172 String channel, String rest)
1173{
1174 Message m = Commands::SetVersion(cnx->bot, rest);
1175 if (m.getCode() < 0)
1176 from->sendNotice(m.getMessage());
1177}
1178
1179void
1180UserCommands::ShitList(ServerConnection *cnx, Person *from,
1181 String channel, String rest)
1182{
1183 from->sendNotice("\002Shitlist:\002");
1184 from->sendNotice("\002Mask Channel Level Expires Reason\002");
1185
1186 for (std::list<ShitEntry *>::iterator it = cnx->bot->shitList->l.begin();
1187 it != cnx->bot->shitList->l.end();
1188 it++)
1189 from->sendNotice((*it)->shitMask.getMask().pad(25) + " " +
1190 (*it)->shitChannelMask.getMask().pad(10) + " " +
1191 String((long)(*it)->shitLevel).pad(9) + " " +
1192 String((long)(*it)->expirationDate).pad(9) + " " +
1193 (*it)->shitReason);
1194
1195 from->sendNotice("\002End of shitlist.\002");
1196}
1197
1198void
1199UserCommands::SpyList(ServerConnection *cnx, Person *from,
1200 String channel, String rest)
1201{
1202 String nick = from->getNick();
1203
1204 from->sendNotice("\002Spy list:\002");
1205
1206 for (std::map<String, Person *, std::less<String> >::iterator it =
1207 cnx->bot->spyList.begin(); it != cnx->bot->spyList.end(); ++it)
1208 from->sendNotice((*it).first);
1209
1210 from->sendNotice("\002End of spy list.\002");
1211}
1212
1213void
1214UserCommands::SpyMessage(ServerConnection *cnx, Person *from,
1215 String channel, String rest)
1216{
1217 String nick = from->getNick();
1218
1219 if (cnx->bot->spyList.find(nick) != cnx->bot->spyList.end()) {
1220 from->sendNotice("\002You are already spying messages.\002");
1221 return;
1222 }
1223
1224 Person *f = from->copy();
1225 f->keepAlive();
1226 cnx->bot->spyList[nick.toLower()] = f;
1227 from->sendNotice("\002You have been added to the spy list.\002");
1228}
1229
1230// FIXME: Convert
1231void
1232UserCommands::Reconnect(ServerConnection *cnx, Person *from,
1233 String channel, String rest)
1234{
1235 String nick = from->getNick();
1236
1237 if (cnx->bot->canChangeServer()) {
1238 cnx->queue->sendQuit("Reconnecting");
1239 cnx->bot->reconnect();
1240 }
1241 else
1242 from->sendNotice("\002I can not change server without losing op on a channel I am on.\002");
1243}
1244
1245void
1246UserCommands::RSpyMessage(ServerConnection *cnx, Person *from,
1247 String channel, String rest)
1248{
1249 String nick = from->getNick().toLower();
1250
1251 if (cnx->bot->spyList.find(nick) == cnx->bot->spyList.end()) {
1252 from->sendNotice("\002You are not in the spy list.\002");
1253 return;
1254 }
1255
1256 delete cnx->bot->spyList[nick];
1257 cnx->bot->spyList.erase(nick);
1258 from->sendNotice("\002You have been removed from the "
1259 "spy list.\002");
1260}
1261
1262// FIXME: Convert
1263void
1264UserCommands::Unlock(ServerConnection *cnx, Person *from,
1265 String channel, String rest)
1266{
1267 cnx->bot->channelList->getChannel(channel)->lockedTopic = false;
1268 from->sendNotice(String("\002Unlocking topic for channel\002 ") +
1269 channel);
1270}
1271
1272void
1273UserCommands::Stats(ServerConnection *cnx, Person *from,
1274 String channel, String rest)
1275{
1276 String nick = from->getNick();
1277
1278 from->sendNotice(String("\002Keeping modes\002 ") +
1279 cnx->bot->channelList->getChannel(channel)->keepModes + " \002on channel\002 " +
1280 channel);
1281}
1282
1283// FIXME: Convert
1284void
1285UserCommands::TBan(ServerConnection *cnx, Person *from,
1286 String channel, String rest)
1287{
1288 Channel * c = cnx->bot->channelList->getChannel(channel);
1289
1290 StringTokenizer st(rest);
1291 String who = st.nextToken();
1292 String t = st.nextToken();
1293 String dest;
1294
1295 if (who == "" || t == "") {
1296 if (from)
1297 from->sendNotice("\002Invalid syntax for this command.\002");
1298 return;
1299 }
1300
1301 if (Utils::isWildcard(who) && from) {
1302 User * u = c->getUser(from->getNick());
1303 if (u && u->getLevel() < User::TRUSTED_USER) {
1304 if (from)
1305 from->sendNotice("\002You need an higher level to use"
1306 " wildcards.\002");
1307 return;
1308 }
1309 }
1310
1311 if (!cnx->bot->iAmOp(channel)) {
1312 if (from)
1313 from->sendNotice(String("\002I am not channel op on\002 ") +
1314 channel);
1315 return;
1316 }
1317
1318 if (!Utils::isWildcard(who))
1319 dest = cnx->bot->getUserhost(channel, who);
1320 else
1321 dest = who;
1322
1323 if (dest == "") {
1324 if (from)
1325 from->sendNotice(String("\002I can not find\002 ") + who);
1326 return;
1327 }
1328
1329 time_t w;
1330
1331 if ((w = Utils::strToTime(t)) == 0) {
1332 if (from)
1333 from->sendNotice(t + " \002is an invalid time.\002");
1334 return;
1335 }
1336
1337 dest = Utils::makeWildcard(dest);
1338 Mask m(dest);
1339
1340 for (std::list<UserListItem *>::iterator it = cnx->bot->userList->l.begin();
1341 it != cnx->bot->userList->l.end();
1342 it++)
1343 if (m.matches((*it)->mask) &&
1344 (*it)->channelMask.matches(channel) &&
1345 (*it)->prot >= User::NO_BAN) {
1346 if (from)
1347 from->sendNotice(String("\002I can not ban\002 ") +
1348 who + " \002on channel\002 " +
1349 channel + " \002(protection).\002");
1350 return;
1351 }
1352
1353 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
1354 it != c->channelBanlist.end(); ++it)
1355 if (m.matches((*it)->banMask))
1356 cnx->queue->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
1357
1358 cnx->bot->channelList->getChannel(channel)->addBan(dest, w);
1359 cnx->queue->sendChannelMode(channel, "+b", dest);
1360 cnx->bot->todoList->addDeban(channel, dest, (time_t)w);
1361}
1362
1363// FIXME: Convert
1364void
1365UserCommands::TKBan(ServerConnection *cnx, Person *from,
1366 String channel, String rest)
1367{
1368 StringTokenizer st(rest);
1369 String who = st.nextToken();
1370 String t = st.nextToken();
1371
1372 TBan(cnx, 0, channel, who + " " + t);
1373 Kick(cnx, from, channel, who + " " + st.rest());
1374}
1375
1376// FIXME: Convert
1377void
1378UserCommands::Topic(ServerConnection *cnx, Person *from,
1379 String channel, String rest)
1380{
1381 String nick = from->getNick();
1382
1383 if (rest.length() == 0) {
1384 if (cnx->bot->channelList->getChannel(channel)->channelTopic == "")
1385 from->sendNotice(String("\002No topic is set for channel\002 ") +
1386 channel + "\002.\002");
1387 else
1388 from->sendNotice(String("\002Topic for\002 ") +
1389 channel + " \002is:\002 " +
1390 cnx->bot->channelList->getChannel(channel)->channelTopic);
1391 } else {
1392 if (cnx->bot->channelList->getChannel(channel)->lockedTopic)
1393 from->sendNotice(String("\002Topic is locked on channel\002 ") +
1394 channel);
1395 else
1396 cnx->queue->sendTopic(channel, rest);
1397 }
1398}
1399
1400void
1401UserCommands::UserList(ServerConnection *cnx, Person *from,
1402 String channel, String rest)
1403{
1404 from->sendNotice("\002Userlist:\002");
1405 from->sendNotice("\002Mask Channel Level Prot Aop Expires\002");
1406
1407 for (std::list<UserListItem *>::iterator it = cnx->bot->userList->l.begin();
1408 it != cnx->bot->userList->l.end();
1409 it++)
1410 from->sendNotice((*it)->mask.getMask().pad(25) + " " +
1411 (*it)->channelMask.getMask().pad(10) + " " +
1412 Utils::levelToStr((*it)->level).pad(12) + " " +
1413 Utils::protToStr((*it)->prot).pad(7) + " " +
1414 Utils::boolToStr((*it)->aop).pad(5) + " " +
1415 String((long)(*it)->expirationDate));
1416
1417 from->sendNotice("\002End of userlist.\002");
1418}
1419
1420void
1421UserCommands::Who(ServerConnection *cnx, Person *from,
1422 String channel, String rest)
1423{
1424 String nick = from->getNick();
1425 User * u = cnx->bot->channelList->getChannel(channel)->getUser(nick);
1426 UserListItem * uli;
1427
1428 if (u)
1429 uli = u->userListItem;
1430 else
1431 uli = cnx->bot->userList->getUserListItem(from->getAddress(),
1432 channel);
1433
1434 if (uli) {
1435 from->sendNotice(String("\002You are\002 ") +
1436 uli->mask.getMask() + " \002on\002 " +
1437 uli->channelMask.getMask());
1438 from->sendNotice(String("\002Lvl:\002 ") +
1439 Utils::levelToStr(uli->level) +
1440 " \002Prot:\002 " +
1441 Utils::protToStr(uli->prot) +
1442 " \002Aop:\002 " +
1443 Utils::boolToStr(uli->aop) +
1444 " \002Expired:\002 " +
1445 Utils::boolToStr(!uli->isStillValid()) +
1446 " \002Ident:\002 " +
1447 (uli && !uli->identified ? "\026" : "") +
1448 Utils::boolToStr(uli && uli->identified) +
1449 (uli && !uli->identified ? "\026" : ""));
1450 } else
1451 from->sendNotice(String("\002You are not in the userlist for\002 ") +
1452 channel);
1453}
1454
1455void
1456UserCommands::Whois(ServerConnection *cnx, Person *from,
1457 String channel, String rest)
1458{
1459 String nick = from->getNick();
1460
1461 if (!rest.length()) {
1462 from->sendNotice("\002No nick specified.\002");
1463 return;
1464 }
1465
1466 StringTokenizer st(rest);
1467 String otherNick = st.nextToken();
1468
1469 User * u = cnx->bot->channelList->getChannel(channel)->getUser(otherNick);
1470 UserListItem * uli;
1471
1472 if (u)
1473 uli = u->userListItem;
1474 else
1475 uli = cnx->bot->userList->getUserListItem(otherNick + "!" +
1476 cnx->bot->getUserhost(channel,
1477 otherNick),
1478 channel);
1479
1480 if (uli) {
1481 from->sendNotice(otherNick +
1482 " \002is\002 " + uli->mask.getMask() +
1483 " \002on\002 " + uli->channelMask.getMask());
1484 from->sendNotice(String("\002Lvl:\002 ") +
1485 Utils::levelToStr(uli->level) +
1486 " \002Prot:\002 " +
1487 Utils::protToStr(uli->prot) +
1488 " \002Aop:\002 " +
1489 Utils::boolToStr(uli->aop) +
1490 " \002Expired:\002 " +
1491 Utils::boolToStr(!uli->isStillValid()) +
1492 " \002Ident:\002 " +
1493 Utils::boolToStr(uli && uli->identified));
1494 } else
1495 from->sendNotice(otherNick +
1496 " \002is not in the userlist for\002 " +
1497 channel);
1498}