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