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