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