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