[project @ 2005-06-30 02:51:27 by unknown_lamer]
[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
39b022cb 17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
cb21075d 18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <fstream>
e07b6b46 24#include <map>
a6339323 25#include <string>
26#include <cctype>
27#include <cstdlib>
cb21075d 28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <netdb.h>
e171dcce 33#include <cstdlib>
cb21075d 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"
6530edbf 48#include "DCCManager.H"
cb21075d 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
57char * crypt(const char *p, const char *s) { return p; }
58#endif
59
60void
61UserCommands::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
69void
70UserCommands::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
a6339323 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();
cb21075d 84
85 if (mask == "" || maskChannel == "" || level == "" ||
86 prot == "" || aop == "") {
87 from->sendNotice("\002Invalid syntax for this command.\002");
88 return;
89 }
90
a6339323 91// if (!Utils::wildcard_p(mask)) {
cb21075d 92// mask = cnx->bot->getUserhost(channel, who);
93// if (mask == "") {
94// from->sendNotice(String("\002I can not find\002 ") + who);
95// return;
96// }
a6339323 97// mask = Utils::make_wildcard(mask);
cb21075d 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;
a6339323 113 if (l > Utils::get_level(cnx->bot, from->getAddress())) {
cb21075d 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
a6339323 124 e = Utils::str2time(expiration);
cb21075d 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 ") +
a6339323 138 Utils::level2str(l) +
cb21075d 139 " \002Protection:\002 " +
a6339323 140 Utils::prot2str(p) +
cb21075d 141 " \002Auto-op:\002 " +
a6339323 142 Utils::bool2str(a));
cb21075d 143 }
144 else
145 from->sendNotice(m.getMessage ());
146
147 // cnx->bot->rehash();
148}
149
150void
151UserCommands::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);
a6339323 160 String serverName = st.next_token();
cb21075d 161 int port = 6667;
162
a6339323 163 if (st.more_tokens_p()) {
164 String temp = st.next_token();
cb21075d 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
179void
180UserCommands::AddShit(ServerConnection *cnx, Person *from,
181 String channel, String rest)
182{
183 StringTokenizer st(rest);
184 String mask, who, maskChannel, level, expiration, reason;
185
a6339323 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());
cb21075d 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 /*
a6339323 204 if (!Utils::wildcard_p(mask)) {
cb21075d 205 mask = cnx->bot->getUserhost(channel, who);
206 if (mask == "") {
207 from->sendNotice(String("\002I can not find\002 ") + who);
208 return;
209 }
a6339323 210 mask = Utils::make_wildcard(mask);
cb21075d 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
a6339323 225 e = Utils::str2time(expiration);
cb21075d 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 ?)
250void
251UserCommands::Alias(ServerConnection *cnx, Person *from,
252 String channel, String rest)
253{
254 StringTokenizer st(rest);
a6339323 255 String newF = Utils::to_upper (st.next_token());
256 String oldF = Utils::to_upper (st.next_token());
cb21075d 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
e07b6b46 264 if (cnx->bot->userFunctions[newF]) {
cb21075d 265 from->sendNotice(newF + " \002is already an alias.\002");
266 return;
e07b6b46 267 }
cb21075d 268
269 // Next, we check that the "old" function exist
e07b6b46 270 if (!cnx->bot->userFunctions[oldF])
271 {
272 from->sendNotice(String("\002I don't know the\002 ") + oldF +
273 " \002command.");
274 return;
cb21075d 275 }
cb21075d 276
277 // Fine, we do the binding
e07b6b46 278 cnx->bot->userFunctions[newF] =
279 new userFunction (*cnx->bot->userFunctions[oldF]);
cb21075d 280
281 from->sendNotice("\002Alias added.\002");
282}
283
284void
285UserCommands::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
299void
300UserCommands::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;
a6339323 325// String mask = who = st.next_token();
326// String maskChannel = st.next_token();
327// String level = st.next_token();
cb21075d 328
329// if (mask == "" || maskChannel == "" || level == "") {
330// from->sendNotice("\002Invalid syntax for this command.\002");
331// return;
332// }
333
a6339323 334// if (!Utils::wildcard_p(mask)) {
cb21075d 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
a6339323 359// if (l > Utils::get_level(cnx->bot, from->getAddress())) {
cb21075d 360// from->sendNotice("\002You can not give a level greater than yours.\002");
361// return;
362// }
363
a6339323 364// if (Utils::get_level(cnx->bot, from->getAddress()) < uli->level) {
cb21075d 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
375void
376UserCommands::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
393void
394UserCommands::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
402void
403UserCommands::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
6530edbf 411 for (DCC_MAP::iterator it =
c3ecc559 412 cnx->bot->dccConnections->dcc_map.begin ();
413 it != cnx->bot->dccConnections->dcc_map.end();
cb21075d 414 ++it) {
4edefeb6 415 from->sendNotice(String(it->second->dcc->get_nuh()).pad(32) + " " +
cb21075d 416 String((long)(current_time -
4edefeb6 417 it->second->dcc->get_lastSpoken())));
cb21075d 418 }
419
420 from->sendNotice("\002End of dcclist.\002");
421}
422
423void
424UserCommands::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
437void
438UserCommands::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
460void
461UserCommands::DelUser(ServerConnection *cnx, Person *from,
462 String channel, String rest)
463{
464 StringTokenizer st(rest);
465
466 String who;
a6339323 467 String mask = who = st.next_token();
468 String maskChannel = st.next_token();
cb21075d 469
470 if (mask == "" || maskChannel == "") {
471 from->sendNotice("\002Invalid syntax for this command.\002");
472 return;
473 }
474
a6339323 475 if (!Utils::wildcard_p(mask)) {
cb21075d 476 mask = cnx->bot->getUserhost(channel, who);
477 if (mask == "") {
478 from->sendNotice(String("\002I can not find\002 ") + who);
479 return;
480 }
a6339323 481 mask = Utils::make_wildcard(mask);
cb21075d 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
496void
497UserCommands::DelShit(ServerConnection *cnx, Person *from,
498 String channel, String rest)
499{
500 StringTokenizer st(rest);
501
502 String who;
a6339323 503 String mask = who = st.next_token();
504 String maskChannel = st.next_token();
cb21075d 505
506 if (mask == "" || maskChannel == "") {
507 from->sendNotice("\002Invalid syntax for this command.\002");
508 return;
509 }
510
a6339323 511 if (!Utils::wildcard_p(mask)) {
cb21075d 512 mask = cnx->bot->getUserhost(channel, who);
513 if (mask == "") {
514 from->sendNotice(String("\002I can not find\002 ") + who);
515 return;
516 }
a6339323 517 mask = Utils::make_wildcard(mask);
cb21075d 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
530void
531UserCommands::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
544void
545UserCommands::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
558void
559UserCommands::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
567void
568UserCommands::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
576void
577UserCommands::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");
a6339323 582 int level = Utils::get_level(cnx->bot, from->getAddress());
cb21075d 583 String result = "";
584 int length = 0;
7b564711 585 std::map<std::string, class userFunction*,
586 std::less<std::string> >::iterator it;
587
588 for (it = cnx->bot->userFunctions.begin();
589 it != cnx->bot->userFunctions.end(); ++it)
590 {
591 if ((*it).second->minLevel <= level)
592 {
593 result = result + (*it).first + " ";
594 length += (*it).first.length() + 1;
595
596 if (length >= 256)
597 {
598 from->sendNotice(result);
599 result = ""; length = 0;
600 }
601 }
602 }
cb21075d 603 if (result != "")
604 from->sendNotice(result);
605 from->sendNotice("\002Use\002 HELP <command> \002for"
606 " help about\002 <command>");
607 return;
608 }
609
610 StringTokenizer st(rest);
a6339323 611 String command = Utils::to_upper (st.next_token());
cb21075d 612 std::ifstream helpFile(cnx->bot->helpFileName);
613
614 if (!helpFile) {
615 from->sendNotice(String("\002Error: I can not find the "
616 "help file\002 ") +
617 cnx->bot->helpFileName);
618 return;
619 }
620
621 String buf;
622 while (!helpFile.eof()) {
623 helpFile >> buf;
624 if (buf.subString(0, command.length()) == String(":") + command) {
625 buf = buf.subString(1);
626 from->sendNotice(String("\002Help for\002 ") + command +
627 "\002:\002");
628 while (buf != "") {
629 from->sendNotice(buf);
630 helpFile >> buf;
631 }
632 from->sendNotice("\002End of help.\002");
633 return;
634 }
635 }
636
637 from->sendNotice(String("\002No such topic (\002") +
638 command + "\002).\002");
639}
640
641void
642UserCommands::Ident(ServerConnection *cnx, Person *from,
643 String channel, String rest)
644{
645 Channel *c = cnx->bot->channelList->getChannel(channel);
646
647 if (rest.length() <= 2) {
648 from->sendNotice("\002No password specified or password "
649 "too short.\002");
650 return;
651 }
652
653 User * u = c->getUser(from->getNick());
654 if (!u) {
655 from->sendNotice(String("\002You can identify yourself on"
656 " channel\002 ") + channel +
657 " \002only if you are on the channel.\002");
658 return;
659 }
660
661 if (u->userListItem && u->userListItem->identified) {
662 from->sendNotice(String("\002You are already identified on"
663 " channel\002 ") + channel);
664 return;
665 }
666
667 if (!u->userListItem) {
668 from->sendNotice("\002You are not in my userlist.\002");
669 return;
670 }
671
672 if (u->userListItem->passwd ==
673 crypt((const char *)rest, (const char *)u->userListItem->passwd)) {
674 // For each channel, we increment identification counter
675 for (std::map<String, Channel *, std::less<String> >::iterator it =
676 cnx->bot->channelList->begin();
677 it != cnx->bot->channelList->end(); ++it)
678 u->userListItem->identified++;
679
680 from->sendNotice("\002You are now identified.\002");
681 } else
682 from->sendNotice("\002This is a wrong password.\002");
683}
684
685void
686UserCommands::Invite(ServerConnection *cnx, Person *from,
687 String channel, String rest)
688{
689 Message m = Commands::Invite(cnx->bot, channel, rest);
690 if (m.getCode() < 0)
691 from->sendNotice(m.getMessage());
692 from->sendNotice(String("\002Inviting\002 ") + rest + " \002on channel\002 " + channel);
693}
694
695// FIXME: Convert
696void
697UserCommands::Join(ServerConnection *cnx, Person *from,
698 String channel, String rest)
699{
700 StringTokenizer st(rest);
a6339323 701 channel = st.next_token();
cb21075d 702
a6339323 703 if (!Utils::valid_channel_name_p(channel)) {
cb21075d 704 from->sendNotice(String("\002") + channel +
705 " is not a valid channel name\002");
706 return;
707 }
708
709 // We change the key only if we are not on the channel. We don't trust
710 // the user...
711 if (!cnx->bot->channelList->getChannel(channel)) {
712 if (cnx->bot->wantedChannels[channel])
713 cnx->bot->wantedChannels[channel]->key = st.rest();
714 else {
715 cnx->bot->wantedChannels[channel] = new wantedChannel("", "", st.rest());
716 }
717 }
718 cnx->queue->sendJoin(channel, cnx->bot->wantedChannels[channel]->key);
719}
720
721// FIXME: Convert
722void
723UserCommands::Keep(ServerConnection *cnx, Person *from,
724 String channel, String rest)
725{
726 String nick = from->getNick();
727
728 if (rest.length() == 0) {
729 from->sendNotice("\002No channel modes specified.\002");
730 return;
731 }
732
733 cnx->bot->channelList->getChannel(channel)->keepModes = rest;
734 from->sendNotice(String("\002Keeping modes\002 ") +
735 rest + " \002on channel\002 " +
736 channel);
737}
738
739// FIXME: Convert
740void
741UserCommands::Kick(ServerConnection *cnx, Person *from,
742 String channel, String rest)
743{
744 String nick = from->getNick();
745
746 Channel * c = cnx->bot->channelList->getChannel(channel);
747
748 if (rest.length() == 0) {
749 from->sendNotice("\002No nick specified.\002");
750 return;
751 }
752
753 StringTokenizer st(rest);
a6339323 754 String who = st.next_token();
cb21075d 755
a6339323 756 if (Utils::wildcard_p(who)) {
cb21075d 757 User * u = c->getUser(nick);
758 if (!u)
759 return;
760 if (u->getLevel() < User::TRUSTED_USER) {
761 from->sendNotice("\002You need an higher level to "
762 "use wildcards.\002");
763 return;
764 }
765 }
766
767 if (!cnx->bot->iAmOp(channel)) {
768 from->sendNotice(String("\002I am not channel op on\002 ") +
769 channel);
770 return;
771 }
772
a6339323 773 if (Utils::wildcard_p(who)) {
cb21075d 774 Mask m(who);
775 for (std::map<String, User *, std::less<String> >::iterator it =
776 c->channelMemory.begin();
777 it != c->channelMemory.end();
778 ++it)
779 if (m.matches((*it).second->nick + "!" +
780 (*it).second->userhost) &&
781 (*it).second->getProt() < User::NO_KICK)
782 cnx->queue->sendKick(channel, (*it).second->nick, st.rest());
783 } else {
784 User * u = c->getUser(who);
785 if (!u) {
786 from->sendNotice(String("\002I can not find\002 ") +
787 who + " \002on\002 " + channel);
788 return;
789 }
790 if (u->getProt() < User::NO_KICK)
791 cnx->queue->sendKick(channel, who, st.rest());
792 else
793 from->sendNotice(String("\002I can not kick\002 ") +
794 who + " \002on\002 " + channel +
795 " \002(protected).\002");
796 }
797}
798
799// FIXME: Convert
800void
801UserCommands::KickBan(ServerConnection *cnx, Person *from,
802 String channel, String rest)
803{
804 StringTokenizer st(rest);
805
a6339323 806 Ban(cnx, 0, channel, st.next_token());
cb21075d 807 Kick(cnx, from, channel, rest);
808}
809
810void
811UserCommands::Load(ServerConnection *cnx, Person *from,
812 String channel, String rest)
813{
814 cnx->bot->shitList->read();
815 cnx->bot->userList->read();
816 cnx->bot->userList->addUserFirst(cnx->bot->nickName + "!" + cnx->bot->userHost, "*", 0, 3, true, -1, "");
817 cnx->bot->rehash();
818 from->sendNotice("\002Userlist and shitlist loaded.\002");
819}
820
821#ifdef USESCRIPTS
822void
823UserCommands::LoadScript(ServerConnection *cnx, Person *from,
824 String channel, String rest)
825{
826 if (rest.length() != 0)
827 Interp::LoadScript(cnx->bot, rest);
828}
829#endif
830
831// FIXME: Convert
832void
833UserCommands::Lock(ServerConnection *cnx, Person *from,
834 String channel, String rest)
835{
836 cnx->bot->channelList->getChannel(channel)->lockedTopic = true;
837 from->sendNotice(String("\002Locking topic for channel\002 ") +
838 channel);
839}
840
841// FIXME: Convert
842void
843UserCommands::Mode(ServerConnection *cnx, Person *from,
844 String channel, String rest)
845{
846 String nick = from->getNick();
847
848 if (rest.length() == 0) {
849 from->sendNotice("\002I need a parameter for this command.\002");
850 return;
851 }
852
853 if (!cnx->bot->iAmOp(channel)) {
854 from->sendNotice(String("\002I am not channel op on\002 ") +
855 channel);
856 return;
857 }
858
859 cnx->queue->sendChannelMode(String("MODE ") + channel + " " + rest);
860}
861
862void
863UserCommands::Msg(ServerConnection *cnx, Person *from,
864 String channel, String rest)
865{
866 StringTokenizer st(rest);
a6339323 867 String who = st.next_token();
cb21075d 868 String message = st.rest();
869
870 Message m = Commands::Msg(cnx->bot, who, message);
871 if (m.getCode() != 0)
872 from->sendNotice(m.getMessage());
873}
874
875void
876UserCommands::Names(ServerConnection *cnx, Person *from,
877 String channel, String rest)
878{
879 String nick = from->getNick();
880 String result = "";
881 int length = 0;
882 Channel *c = cnx->bot->channelList->getChannel(channel);
883 std::map<String, User *, std::less<String> >::iterator it;
884
885 from->sendNotice(String("\002Names on ") +
886 channel + ":\002");
887
888 for (it = c->channelMemory.begin();
889 it != c->channelMemory.end(); ++it) {
890 result = result +
891 ((*it).second->mode & User::OP_MODE ? "@" :
892 ((*it).second->mode & User::VOICE_MODE ? "+" : "")) +
893 (*it).second->nick + " ";
894 length += (*it).first.length() + 1;
895 if (length >= 256) {
896 from->sendNotice(result);
897 result = ""; length = 0;
898 }
899 }
900
901 if (result != "")
902 from->sendNotice(result);
903
904 from->sendNotice("\002End of names.\002");
905}
906
907// FIXME: Convert
908void
909UserCommands::NextServer(ServerConnection *cnx, Person *from,
910 String channel, String rest)
911{
912 if (cnx->bot->serverList->size() == 0) {
913 from->sendNotice("\002Server list is empty !\002");
914 return;
915 }
916
917 if (cnx->bot->serverList->size() == 1) {
918 from->sendNotice("\002Server list has only one item. Use"
919 " \"reconnect\" to force reconnection.\002");
920 return;
921 }
922
923 if (cnx->bot->canChangeServer()) {
924 cnx->queue->sendQuit("Changing server");
925 cnx->bot->nextServer();
926 }
927 else
928 from->sendNotice("\002I can not change server without"
929 " losing op on a channel I am on.\002");
930}
931
932// FIXME: Convert
933void
934UserCommands::Nick(ServerConnection *cnx, Person *from,
935 String channel, String rest)
936{
937 // We parse the parameters
938 StringTokenizer st(rest);
a6339323 939 String nick = st.next_token();
cb21075d 940
941 if (rest == "") {
942 from->sendNotice(String("\002No nickname given.\002"));
943 return;
944 }
945
6b7614a8 946 if (!Utils::valid_nickname_p (cnx->bot, nick)) {
cb21075d 947 from->sendNotice(String("\002") + nick +
948 " is not a valid nickname\002");
949 return;
950 }
951
952 cnx->bot->wantedNickName = nick;
953 cnx->queue->sendNick(nick);
954}
955
956void
957UserCommands::NsLookup(ServerConnection *cnx, Person *from,
958 String channel, String rest)
959{
960 String target;
961
962 if (rest.length() == 0) {
963 from->sendNotice("\002You need to supply a nick or an "
964 "host for this command.\002");
965 return;
966 }
967
968 if (rest.find('.') == -1) {
969 StringTokenizer st(cnx->bot->getUserhost("", rest));
a6339323 970 st.next_token('@');
cb21075d 971 target = st.rest();
972 if (target.length() == 0) {
973 from->sendNotice(String("\002I could not find\002 ") +
974 target);
975 return;
976 }
977 } else
978 target = rest;
979
980 struct hostent * host;
981 struct in_addr iaddr;
982
983 if (isdigit(target[0])) { // An IP ?
984 iaddr.s_addr = inet_addr((const char *)target);
985 host = gethostbyaddr((char *)(&iaddr),
986 sizeof(struct in_addr),
987 AF_INET);
988 if (host) {
989 from->sendNotice(target +
990 " \002is the IP address of\002 " +
991 host->h_name);
992 return;
993 }
994 } else {
995 host = gethostbyname((const char *)target);
996 if (host) {
997 memcpy((char *)&iaddr, (char *)host->h_addr,
998 host->h_length);
999 from->sendNotice(target + " \002has\002 " +
1000 inet_ntoa(iaddr) + " \002for IP address.\002");
1001 return;
1002 }
1003 }
1004
1005 from->sendNotice(String("\002I could not find host\002 ") +
1006 target);
1007}
1008
1009// FIXME: Convert
1010void
1011UserCommands::Op(ServerConnection *cnx, Person *from,
1012 String channel, String rest)
1013{
1014 String nick = from->getNick();
1015
1016 if (!cnx->bot->iAmOp(channel)) {
1017 from->sendNotice(String("\002I am not channel op on\002 ") +
1018 channel);
1019 return;
1020 }
1021
a6339323 1022 if (Utils::wildcard_p(rest)) {
cb21075d 1023 from->sendNotice("\002Mass op is not allowed.\002");
1024 return;
1025 }
1026
1027 String target;
1028
1029 if (rest.length() == 0)
1030 target = nick;
1031 else
1032 target = rest;
1033
1034 User *u = cnx->bot->channelList->getChannel(channel)->getUser(target);
1035 if (!u) {
1036 from->sendNotice(String("\002I cannot find\002 ") + target + " \002on channel\002 " + channel);
1037 return;
1038 }
1039
1040 ShitEntry *se = cnx->bot->shitList->getShit(target, channel);
1041 if (se && se->isStillValid() && se->getShitLevel() >= ShitEntry::SHIT_NOOP) {
1042 from->sendNotice(String("\002I can not op\002 ")+target+" \002on channel\002 "+channel+" \002(shitlist).\002");
1043 return;
1044 }
1045
1046 if (!(u->mode & User::OP_MODE))
1047 cnx->queue->sendChannelMode(channel, "+o", target);
1048 else {
1049 if (target == nick)
1050 from->sendNotice(String("\002You are already channel "
1051 "operator on\002 ") + channel);
1052 else
1053 from->sendNotice(target + " \002is already channel "
1054 "operator on\002 " + channel);
1055 }
1056}
1057
1058// FIXME: Convert
1059void
1060UserCommands::Part(ServerConnection *cnx, Person *from,
1061 String channel, String rest)
1062{
1063 wantedChannel *w = cnx->bot->wantedChannels[channel];
1064 cnx->bot->wantedChannels.erase(channel);
1065 delete w;
1066 cnx->queue->sendPart(channel);
1067}
1068
1069void
1070UserCommands::Password(ServerConnection *cnx, Person *from,
1071 String channel, String rest)
1072{
1073 Channel *c = cnx->bot->channelList->getChannel(channel);
1074
1075 if (rest.length() == 0) {
1076 from->sendNotice("\002No password.\002");
1077 return;
1078 }
1079
1080 User * u = c->getUser(from->getNick());
1081 if (!u) {
1082 from->sendNotice(String("\002To change your password for\002") +
1083 channel + "\002, you need to be on the "
1084 "channel.\002");
1085 return;
1086 }
1087
1088 if (!u->userListItem) {
1089 from->sendNotice("\002You are not in my userlist.\002");
1090 return;
1091 }
1092
1093 if (rest.toLower() == "none") {
1094 u->userListItem->passwd = "";
1095 from->sendNotice("\002Password cleared.\002");
1096 return;
1097 }
1098
1099 static char saltChars[] = "abcdefghijklmnopqrstuvwxyz"
1100 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
1101 char salt[3];
1102 srand(time(0));
1103 salt[0] = saltChars[rand() % 64];
1104 salt[1] = saltChars[rand() % 64];
1105 salt[2] = '\0';
1106
1107 u->userListItem->passwd = crypt((const char *)rest, salt);
1108 from->sendNotice("\002Password changed.\002");
1109}
1110
1111void
1112UserCommands::Save(ServerConnection *cnx, Person *from,
1113 String channel, String rest)
1114{
1115 cnx->bot->userList->save();
1116 cnx->bot->shitList->save();
1117 from->sendNotice("\002Userlist and shitlist saved.\002");
1118}
1119
1120// FIXME: Convert
1121void
1122UserCommands::Say(ServerConnection *cnx, Person *from,
1123 String channel, String rest)
1124{
1125 if (rest.length() != 0)
1126 cnx->queue->sendPrivmsg(channel, rest);
1127}
1128
1129// FIXME: Convert
1130void
1131UserCommands::Server(ServerConnection *cnx, Person *from,
1132 String channel, String rest)
1133{
1134 int serverNumber;
1135 String nick = from->getNick();
1136
1137 if (rest.length() == 0) {
1138 from->sendNotice("\002You need to supply a server number for this command.\002");
1139 return;
1140 }
1141
1142 serverNumber = atoi(rest);
1143
1144 if (serverNumber < 0 || serverNumber >= cnx->bot->serverList->size()) {
1145 from->sendNotice(String((long)serverNumber) +
1146 " \002is an invalid server number (see the serverlist).\002");
1147 return;
1148 }
1149
1150 if (cnx->bot->canChangeServer()) {
1151 cnx->queue->sendQuit("Changing server");
1152 cnx->queue->flush();
1153 cnx->bot->connect(serverNumber);
1154 }
1155 else
1156 from->sendNotice("\002I can not change server without losing op on a channel I am on.\002");
1157}
1158
1159void
1160UserCommands::ServerList(ServerConnection *cnx, Person *from,
1161 String channel, String rest)
1162{
1163 String nick = from->getNick();
1164
1165 from->sendNotice("\002Server list:\002");
1166 long l = 0;
1167 String s;
1168 for (std::vector<class Server *>::iterator it =
1169 cnx->bot->serverList->v.begin();
1170 it != cnx->bot->serverList->v.end();
1171 ++it) {
1172 s = (*it) == cnx->server ? "\026" : "";
1173 from->sendNotice(s + String(l++) + s + " " +
1174 (*it)->getHostName() +
1175 " (" + String((long)((*it)->getPort())) +
1176 ")");
1177 }
1178 from->sendNotice("\002End of server list.\002");
1179}
1180
e171dcce 1181
1182void
1183UserCommands::SetFloodRate(ServerConnection *cnx, Person *from,
1184 String channel, String rest)
1185{
1186 Message m = Commands::SetFloodRate (cnx->bot, std::atoi (rest));
1187 if (m.getCode ())
1188 from->sendNotice (m.getMessage ());
1189 else
1190 from->sendNotice ("Flood Rate set to:" + String(std::atol(rest)));
1191}
1192
cb21075d 1193void
1194UserCommands::SetVersion(ServerConnection *cnx, Person *from,
1195 String channel, String rest)
1196{
1197 Message m = Commands::SetVersion(cnx->bot, rest);
6b7614a8 1198
cb21075d 1199 if (m.getCode() < 0)
6b7614a8 1200 {
1201 Commands::Notice (cnx->bot, from->getNick (), m.getMessage());
1202 }
cb21075d 1203}
1204
1205void
1206UserCommands::ShitList(ServerConnection *cnx, Person *from,
1207 String channel, String rest)
1208{
1209 from->sendNotice("\002Shitlist:\002");
1210 from->sendNotice("\002Mask Channel Level Expires Reason\002");
1211
1212 for (std::list<ShitEntry *>::iterator it = cnx->bot->shitList->l.begin();
1213 it != cnx->bot->shitList->l.end();
1214 it++)
1215 from->sendNotice((*it)->shitMask.getMask().pad(25) + " " +
1216 (*it)->shitChannelMask.getMask().pad(10) + " " +
1217 String((long)(*it)->shitLevel).pad(9) + " " +
1218 String((long)(*it)->expirationDate).pad(9) + " " +
1219 (*it)->shitReason);
1220
1221 from->sendNotice("\002End of shitlist.\002");
1222}
1223
1224void
1225UserCommands::SpyList(ServerConnection *cnx, Person *from,
1226 String channel, String rest)
1227{
1228 String nick = from->getNick();
1229
1230 from->sendNotice("\002Spy list:\002");
1231
1232 for (std::map<String, Person *, std::less<String> >::iterator it =
1233 cnx->bot->spyList.begin(); it != cnx->bot->spyList.end(); ++it)
1234 from->sendNotice((*it).first);
1235
1236 from->sendNotice("\002End of spy list.\002");
1237}
1238
1239void
1240UserCommands::SpyMessage(ServerConnection *cnx, Person *from,
1241 String channel, String rest)
1242{
1243 String nick = from->getNick();
1244
1245 if (cnx->bot->spyList.find(nick) != cnx->bot->spyList.end()) {
1246 from->sendNotice("\002You are already spying messages.\002");
1247 return;
1248 }
1249
1250 Person *f = from->copy();
1251 f->keepAlive();
1252 cnx->bot->spyList[nick.toLower()] = f;
1253 from->sendNotice("\002You have been added to the spy list.\002");
1254}
1255
1256// FIXME: Convert
1257void
1258UserCommands::Reconnect(ServerConnection *cnx, Person *from,
1259 String channel, String rest)
1260{
1261 String nick = from->getNick();
1262
1263 if (cnx->bot->canChangeServer()) {
1264 cnx->queue->sendQuit("Reconnecting");
1265 cnx->bot->reconnect();
1266 }
1267 else
1268 from->sendNotice("\002I can not change server without losing op on a channel I am on.\002");
1269}
1270
1271void
1272UserCommands::RSpyMessage(ServerConnection *cnx, Person *from,
1273 String channel, String rest)
1274{
1275 String nick = from->getNick().toLower();
1276
1277 if (cnx->bot->spyList.find(nick) == cnx->bot->spyList.end()) {
1278 from->sendNotice("\002You are not in the spy list.\002");
1279 return;
1280 }
1281
1282 delete cnx->bot->spyList[nick];
1283 cnx->bot->spyList.erase(nick);
1284 from->sendNotice("\002You have been removed from the "
1285 "spy list.\002");
1286}
1287
1288// FIXME: Convert
1289void
1290UserCommands::Unlock(ServerConnection *cnx, Person *from,
1291 String channel, String rest)
1292{
1293 cnx->bot->channelList->getChannel(channel)->lockedTopic = false;
1294 from->sendNotice(String("\002Unlocking topic for channel\002 ") +
1295 channel);
1296}
1297
1298void
1299UserCommands::Stats(ServerConnection *cnx, Person *from,
1300 String channel, String rest)
1301{
1302 String nick = from->getNick();
1303
1304 from->sendNotice(String("\002Keeping modes\002 ") +
1305 cnx->bot->channelList->getChannel(channel)->keepModes + " \002on channel\002 " +
1306 channel);
1307}
1308
1309// FIXME: Convert
1310void
1311UserCommands::TBan(ServerConnection *cnx, Person *from,
1312 String channel, String rest)
1313{
1314 Channel * c = cnx->bot->channelList->getChannel(channel);
1315
1316 StringTokenizer st(rest);
a6339323 1317 String who = st.next_token();
1318 String t = st.next_token();
cb21075d 1319 String dest;
1320
1321 if (who == "" || t == "") {
1322 if (from)
1323 from->sendNotice("\002Invalid syntax for this command.\002");
1324 return;
1325 }
1326
a6339323 1327 if (Utils::wildcard_p(who) && from) {
cb21075d 1328 User * u = c->getUser(from->getNick());
1329 if (u && u->getLevel() < User::TRUSTED_USER) {
1330 if (from)
1331 from->sendNotice("\002You need an higher level to use"
1332 " wildcards.\002");
1333 return;
1334 }
1335 }
1336
1337 if (!cnx->bot->iAmOp(channel)) {
1338 if (from)
1339 from->sendNotice(String("\002I am not channel op on\002 ") +
1340 channel);
1341 return;
1342 }
1343
a6339323 1344 if (!Utils::wildcard_p(who))
cb21075d 1345 dest = cnx->bot->getUserhost(channel, who);
1346 else
1347 dest = who;
1348
1349 if (dest == "") {
1350 if (from)
1351 from->sendNotice(String("\002I can not find\002 ") + who);
1352 return;
1353 }
1354
1355 time_t w;
1356
a6339323 1357 if ((w = Utils::str2time(t)) == 0) {
cb21075d 1358 if (from)
1359 from->sendNotice(t + " \002is an invalid time.\002");
1360 return;
1361 }
1362
a6339323 1363 dest = Utils::make_wildcard(dest);
cb21075d 1364 Mask m(dest);
1365
1366 for (std::list<UserListItem *>::iterator it = cnx->bot->userList->l.begin();
1367 it != cnx->bot->userList->l.end();
1368 it++)
1369 if (m.matches((*it)->mask) &&
1370 (*it)->channelMask.matches(channel) &&
1371 (*it)->prot >= User::NO_BAN) {
1372 if (from)
1373 from->sendNotice(String("\002I can not ban\002 ") +
1374 who + " \002on channel\002 " +
1375 channel + " \002(protection).\002");
1376 return;
1377 }
1378
1379 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
1380 it != c->channelBanlist.end(); ++it)
1381 if (m.matches((*it)->banMask))
1382 cnx->queue->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
1383
1384 cnx->bot->channelList->getChannel(channel)->addBan(dest, w);
1385 cnx->queue->sendChannelMode(channel, "+b", dest);
1386 cnx->bot->todoList->addDeban(channel, dest, (time_t)w);
1387}
1388
1389// FIXME: Convert
1390void
1391UserCommands::TKBan(ServerConnection *cnx, Person *from,
1392 String channel, String rest)
1393{
1394 StringTokenizer st(rest);
a6339323 1395 String who = st.next_token();
1396 String t = st.next_token();
cb21075d 1397
1398 TBan(cnx, 0, channel, who + " " + t);
1399 Kick(cnx, from, channel, who + " " + st.rest());
1400}
1401
1402// FIXME: Convert
1403void
1404UserCommands::Topic(ServerConnection *cnx, Person *from,
1405 String channel, String rest)
1406{
1407 String nick = from->getNick();
1408
1409 if (rest.length() == 0) {
1410 if (cnx->bot->channelList->getChannel(channel)->channelTopic == "")
1411 from->sendNotice(String("\002No topic is set for channel\002 ") +
1412 channel + "\002.\002");
1413 else
1414 from->sendNotice(String("\002Topic for\002 ") +
1415 channel + " \002is:\002 " +
1416 cnx->bot->channelList->getChannel(channel)->channelTopic);
1417 } else {
1418 if (cnx->bot->channelList->getChannel(channel)->lockedTopic)
1419 from->sendNotice(String("\002Topic is locked on channel\002 ") +
1420 channel);
1421 else
1422 cnx->queue->sendTopic(channel, rest);
1423 }
1424}
1425
1426void
1427UserCommands::UserList(ServerConnection *cnx, Person *from,
1428 String channel, String rest)
1429{
1430 from->sendNotice("\002Userlist:\002");
1431 from->sendNotice("\002Mask Channel Level Prot Aop Expires\002");
1432
1433 for (std::list<UserListItem *>::iterator it = cnx->bot->userList->l.begin();
1434 it != cnx->bot->userList->l.end();
1435 it++)
a6339323 1436 from->sendNotice((*it)->mask.getMask().pad(25)
1437 + " "
1438 + (*it)->channelMask.getMask().pad(10)
1439 + " " +
1440 String(Utils::level2str((*it)->level)).pad(12)
1441 + " " +
1442 String(Utils::prot2str((*it)->prot)).pad(7)
1443 + " " +
1444 String(Utils::bool2str((*it)->aop)).pad(5)
1445 + " " +
1446 String(Utils::long2str ((*it)->expirationDate)));
1447
cb21075d 1448 from->sendNotice("\002End of userlist.\002");
1449}
1450
1451void
1452UserCommands::Who(ServerConnection *cnx, Person *from,
1453 String channel, String rest)
1454{
1455 String nick = from->getNick();
1456 User * u = cnx->bot->channelList->getChannel(channel)->getUser(nick);
1457 UserListItem * uli;
1458
1459 if (u)
1460 uli = u->userListItem;
1461 else
1462 uli = cnx->bot->userList->getUserListItem(from->getAddress(),
1463 channel);
1464
1465 if (uli) {
1466 from->sendNotice(String("\002You are\002 ") +
1467 uli->mask.getMask() + " \002on\002 " +
1468 uli->channelMask.getMask());
1469 from->sendNotice(String("\002Lvl:\002 ") +
a6339323 1470 Utils::level2str(uli->level) +
cb21075d 1471 " \002Prot:\002 " +
a6339323 1472 Utils::prot2str(uli->prot) +
cb21075d 1473 " \002Aop:\002 " +
a6339323 1474 Utils::bool2str(uli->aop) +
cb21075d 1475 " \002Expired:\002 " +
a6339323 1476 Utils::bool2str(!uli->isStillValid()) +
cb21075d 1477 " \002Ident:\002 " +
1478 (uli && !uli->identified ? "\026" : "") +
a6339323 1479 Utils::bool2str(uli && uli->identified) +
cb21075d 1480 (uli && !uli->identified ? "\026" : ""));
1481 } else
1482 from->sendNotice(String("\002You are not in the userlist for\002 ") +
1483 channel);
1484}
1485
1486void
1487UserCommands::Whois(ServerConnection *cnx, Person *from,
1488 String channel, String rest)
1489{
1490 String nick = from->getNick();
1491
1492 if (!rest.length()) {
1493 from->sendNotice("\002No nick specified.\002");
1494 return;
1495 }
1496
1497 StringTokenizer st(rest);
a6339323 1498 String otherNick = st.next_token();
cb21075d 1499
1500 User * u = cnx->bot->channelList->getChannel(channel)->getUser(otherNick);
1501 UserListItem * uli;
1502
1503 if (u)
1504 uli = u->userListItem;
1505 else
1506 uli = cnx->bot->userList->getUserListItem(otherNick + "!" +
1507 cnx->bot->getUserhost(channel,
1508 otherNick),
1509 channel);
1510
1511 if (uli) {
1512 from->sendNotice(otherNick +
1513 " \002is\002 " + uli->mask.getMask() +
1514 " \002on\002 " + uli->channelMask.getMask());
1515 from->sendNotice(String("\002Lvl:\002 ") +
a6339323 1516 Utils::level2str(uli->level) +
cb21075d 1517 " \002Prot:\002 " +
a6339323 1518 Utils::prot2str(uli->prot) +
cb21075d 1519 " \002Aop:\002 " +
a6339323 1520 Utils::bool2str(uli->aop) +
cb21075d 1521 " \002Expired:\002 " +
a6339323 1522 Utils::bool2str(!uli->isStillValid()) +
cb21075d 1523 " \002Ident:\002 " +
a6339323 1524 Utils::bool2str(uli && uli->identified));
cb21075d 1525 } else
1526 from->sendNotice(otherNick +
1527 " \002is not in the userlist for\002 " +
1528 channel);
1529}