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