Improve BanEntry
[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
18 // 02110-1301, USA.
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "UserCommands.H"
25
26 #include <fstream>
27 #include <map>
28 #include <string>
29
30 #include <cctype>
31 #include <cstdlib>
32 #include <cstring>
33
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <netdb.h>
39
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
49
50 #include <unistd.h>
51
52 #include "BanEntry.H"
53 #include "Channel.H"
54 #include "ChannelList.H"
55 #include "Commands.H"
56 #include "DCCConnection.H"
57 #include "DCCManager.H"
58 #include "DCCPerson.H"
59 #include "Macros.H"
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"
68 #include "StringTokenizer.H"
69 #include "TodoList.H"
70 #include "User.H"
71 #include "UserList.H"
72 #include "Utils.H"
73
74 #ifdef USESCRIPTS
75 #include "Interp.H"
76 #endif
77
78 #ifdef NOCRYPT
79 char * crypt(const char *p, const char *s) { return p; }
80 #endif
81
82 void
83 UserCommands::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
91 void
92 UserCommands::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
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();
106
107 if (mask == "" || maskChannel == "" || level == "" ||
108 prot == "" || aop == "") {
109 from->sendNotice("\002Invalid syntax for this command.\002");
110 return;
111 }
112
113 // if (!Utils::wildcard_p(mask)) {
114 // mask = cnx->bot->getUserhost(channel, who);
115 // if (mask == "") {
116 // from->sendNotice(String("\002I can not find\002 ") + who);
117 // return;
118 // }
119 // mask = Utils::make_wildcard(mask);
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;
135 if (l > Utils::get_level(cnx->bot, from->getAddress())) {
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
146 e = Utils::str2time(expiration);
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 ") +
160 Utils::level2str(l) +
161 " \002Protection:\002 " +
162 Utils::prot2str(p) +
163 " \002Auto-op:\002 " +
164 Utils::bool2str(a));
165 }
166 else
167 from->sendNotice(m.getMessage ());
168
169 // cnx->bot->rehash();
170 }
171
172 void
173 UserCommands::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);
182 String serverName = st.next_token();
183 int port = 6667;
184
185 if (st.more_tokens_p()) {
186 String temp = st.next_token();
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
201 void
202 UserCommands::AddShit(ServerConnection *cnx, Person *from,
203 String channel, String rest)
204 {
205 StringTokenizer st(rest);
206 String mask, who, maskChannel, level, expiration, reason;
207
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());
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 /*
226 if (!Utils::wildcard_p(mask)) {
227 mask = cnx->bot->getUserhost(channel, who);
228 if (mask == "") {
229 from->sendNotice(String("\002I can not find\002 ") + who);
230 return;
231 }
232 mask = Utils::make_wildcard(mask);
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
247 e = Utils::str2time(expiration);
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 ?)
272 void
273 UserCommands::Alias(ServerConnection *cnx, Person *from,
274 String channel, String rest)
275 {
276 StringTokenizer st(rest);
277 String newF = Utils::to_upper (st.next_token());
278 String oldF = Utils::to_upper (st.next_token());
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
286 if (cnx->bot->userFunctions[newF]) {
287 from->sendNotice(newF + " \002is already an alias.\002");
288 return;
289 }
290
291 // Next, we check that the "old" function exist
292 if (!cnx->bot->userFunctions[oldF])
293 {
294 from->sendNotice(String("\002I don't know the\002 ") + oldF +
295 " \002command.");
296 return;
297 }
298
299 // Fine, we do the binding
300 cnx->bot->userFunctions[newF] =
301 new userFunction (*cnx->bot->userFunctions[oldF]);
302
303 from->sendNotice("\002Alias added.\002");
304 }
305
306 void
307 UserCommands::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
321 void
322 UserCommands::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().getMask().pad(30) + " -1");
334 else
335 from->sendNotice((*it)->getMask().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;
347 // String mask = who = st.next_token();
348 // String maskChannel = st.next_token();
349 // String level = st.next_token();
350
351 // if (mask == "" || maskChannel == "" || level == "") {
352 // from->sendNotice("\002Invalid syntax for this command.\002");
353 // return;
354 // }
355
356 // if (!Utils::wildcard_p(mask)) {
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
381 // if (l > Utils::get_level(cnx->bot, from->getAddress())) {
382 // from->sendNotice("\002You can not give a level greater than yours.\002");
383 // return;
384 // }
385
386 // if (Utils::get_level(cnx->bot, from->getAddress()) < uli->level) {
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
397 void
398 UserCommands::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
415 void
416 UserCommands::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
424 void
425 UserCommands::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
433 for (DCC_MAP::iterator it =
434 cnx->bot->dccConnections->dcc_map.begin ();
435 it != cnx->bot->dccConnections->dcc_map.end();
436 ++it) {
437 from->sendNotice(String(it->second->dcc->get_nuh()).pad(32) + " " +
438 String((long)(current_time -
439 it->second->dcc->get_lastSpoken())));
440 }
441
442 from->sendNotice("\002End of dcclist.\002");
443 }
444
445 void
446 UserCommands::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
459 void
460 UserCommands::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
482 void
483 UserCommands::DelUser(ServerConnection *cnx, Person *from,
484 String channel, String rest)
485 {
486 StringTokenizer st(rest);
487
488 String who;
489 String mask = who = st.next_token();
490 String maskChannel = st.next_token();
491
492 if (mask == "" || maskChannel == "") {
493 from->sendNotice("\002Invalid syntax for this command.\002");
494 return;
495 }
496
497 if (!Utils::wildcard_p(mask)) {
498 mask = cnx->bot->getUserhost(channel, who);
499 if (mask == "") {
500 from->sendNotice(String("\002I can not find\002 ") + who);
501 return;
502 }
503 mask = Utils::make_wildcard(mask);
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
518 void
519 UserCommands::DelShit(ServerConnection *cnx, Person *from,
520 String channel, String rest)
521 {
522 StringTokenizer st(rest);
523
524 String who;
525 String mask = who = st.next_token();
526 String maskChannel = st.next_token();
527
528 if (mask == "" || maskChannel == "") {
529 from->sendNotice("\002Invalid syntax for this command.\002");
530 return;
531 }
532
533 if (!Utils::wildcard_p(mask)) {
534 mask = cnx->bot->getUserhost(channel, who);
535 if (mask == "") {
536 from->sendNotice(String("\002I can not find\002 ") + who);
537 return;
538 }
539 mask = Utils::make_wildcard(mask);
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
552 void
553 UserCommands::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
566 void
567 UserCommands::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
580 void
581 UserCommands::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
589 void
590 UserCommands::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
598 void
599 UserCommands::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");
604 int level = Utils::get_level(cnx->bot, from->getAddress());
605 String result = "";
606 int length = 0;
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 }
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);
633 String command = Utils::to_upper (st.next_token());
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
663 void
664 UserCommands::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
707 void
708 UserCommands::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
718 void
719 UserCommands::Join(ServerConnection *cnx, Person *from,
720 String channel, String rest)
721 {
722 StringTokenizer st(rest);
723 channel = st.next_token();
724
725 if (!Utils::valid_channel_name_p(channel)) {
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
744 void
745 UserCommands::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
762 void
763 UserCommands::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);
776 String who = st.next_token();
777
778 if (Utils::wildcard_p(who)) {
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
795 if (Utils::wildcard_p(who)) {
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
822 void
823 UserCommands::KickBan(ServerConnection *cnx, Person *from,
824 String channel, String rest)
825 {
826 StringTokenizer st(rest);
827
828 Ban(cnx, 0, channel, st.next_token());
829 Kick(cnx, from, channel, rest);
830 }
831
832 void
833 UserCommands::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
844 void
845 UserCommands::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
854 void
855 UserCommands::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
864 void
865 UserCommands::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
884 void
885 UserCommands::Msg(ServerConnection *cnx, Person *from,
886 String channel, String rest)
887 {
888 StringTokenizer st(rest);
889 String who = st.next_token();
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
897 void
898 UserCommands::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
930 void
931 UserCommands::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
955 void
956 UserCommands::Nick(ServerConnection *cnx, Person *from,
957 String channel, String rest)
958 {
959 // We parse the parameters
960 StringTokenizer st(rest);
961 String nick = st.next_token();
962
963 if (rest == "") {
964 from->sendNotice(String("\002No nickname given.\002"));
965 return;
966 }
967
968 if (!Utils::valid_nickname_p (cnx->bot, nick)) {
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
978 void
979 UserCommands::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));
992 st.next_token('@');
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) {
1019 std::memcpy((char *)&iaddr, (char *)host->h_addr,
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
1032 void
1033 UserCommands::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
1044 if (Utils::wildcard_p(rest)) {
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
1081 void
1082 UserCommands::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
1091 void
1092 UserCommands::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
1133 void
1134 UserCommands::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
1143 void
1144 UserCommands::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
1152 void
1153 UserCommands::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
1181 void
1182 UserCommands::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
1203
1204 void
1205 UserCommands::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
1215 void
1216 UserCommands::SetVersion(ServerConnection *cnx, Person *from,
1217 String channel, String rest)
1218 {
1219 Message m = Commands::SetVersion(cnx->bot, rest);
1220
1221 if (m.getCode() < 0)
1222 {
1223 Commands::Notice (cnx->bot, from->getNick (), m.getMessage());
1224 }
1225 }
1226
1227 void
1228 UserCommands::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
1246 void
1247 UserCommands::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
1261 void
1262 UserCommands::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
1279 void
1280 UserCommands::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
1293 void
1294 UserCommands::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
1311 void
1312 UserCommands::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
1320 void
1321 UserCommands::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
1332 void
1333 UserCommands::TBan(ServerConnection *cnx, Person *from,
1334 String channel, String rest)
1335 {
1336 Channel * c = cnx->bot->channelList->getChannel(channel);
1337
1338 StringTokenizer st(rest);
1339 String who = st.next_token();
1340 String t = st.next_token();
1341 String dest;
1342
1343 if (who == "" || t == "") {
1344 if (from)
1345 from->sendNotice("\002Invalid syntax for this command.\002");
1346 return;
1347 }
1348
1349 if (Utils::wildcard_p(who) && from) {
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
1366 if (!Utils::wildcard_p(who))
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
1379 if ((w = Utils::str2time(t)) == 0) {
1380 if (from)
1381 from->sendNotice(t + " \002is an invalid time.\002");
1382 return;
1383 }
1384
1385 dest = Utils::make_wildcard(dest);
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)->getMask()))
1404 cnx->queue->sendChannelMode(channel, "-b", (*it)->getMask().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
1412 void
1413 UserCommands::TKBan(ServerConnection *cnx, Person *from,
1414 String channel, String rest)
1415 {
1416 StringTokenizer st(rest);
1417 String who = st.next_token();
1418 String t = st.next_token();
1419
1420 TBan(cnx, 0, channel, who + " " + t);
1421 Kick(cnx, from, channel, who + " " + st.rest());
1422 }
1423
1424 // FIXME: Convert
1425 void
1426 UserCommands::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
1448 void
1449 UserCommands::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++)
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
1470 from->sendNotice("\002End of userlist.\002");
1471 }
1472
1473 void
1474 UserCommands::Who(ServerConnection *cnx, Person *from,
1475 String channel, String rest)
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 ") +
1492 Utils::level2str(uli->level) +
1493 " \002Prot:\002 " +
1494 Utils::prot2str(uli->prot) +
1495 " \002Aop:\002 " +
1496 Utils::bool2str(uli->aop) +
1497 " \002Expired:\002 " +
1498 Utils::bool2str(!uli->isStillValid()) +
1499 " \002Ident:\002 " +
1500 (uli && !uli->identified ? "\026" : "") +
1501 Utils::bool2str(uli && uli->identified) +
1502 (uli && !uli->identified ? "\026" : ""));
1503 } else
1504 from->sendNotice(String("\002You are not in the userlist for\002 ") +
1505 channel);
1506 }
1507
1508 void
1509 UserCommands::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);
1520 String otherNick = st.next_token();
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 ") +
1538 Utils::level2str(uli->level) +
1539 " \002Prot:\002 " +
1540 Utils::prot2str(uli->prot) +
1541 " \002Aop:\002 " +
1542 Utils::bool2str(uli->aop) +
1543 " \002Expired:\002 " +
1544 Utils::bool2str(!uli->isStillValid()) +
1545 " \002Ident:\002 " +
1546 Utils::bool2str(uli && uli->identified));
1547 } else
1548 from->sendNotice(otherNick +
1549 " \002is not in the userlist for\002 " +
1550 channel);
1551 }