1 /*
2 * numbers.c: handles all those strange numeric response dished out by that
3 * wacky, nutty program we call ircd
4 *
5 * Written by Michael Sandrof
6 *
7 * Copyright (c) 1990 Michael Sandrof.
8 * Copyright (c) 1991, 1992 Troy Rollo.
9 * Copyright (c) 1992-2000 Matthew R. Green.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "irc.h"
37 IRCII_RCSID("@(#)$Id: numbers.c,v 1.57 2000/07/18 17:12:21 mrg Exp $");
38
39 #include "input.h"
40 #include "edit.h"
41 #include "ircaux.h"
42 #include "vars.h"
43 #include "lastlog.h"
44 #include "hook.h"
45 #include "server.h"
46 #include "whois.h"
47 #include "numbers.h"
48 #include "window.h"
49 #include "screen.h"
50 #include "output.h"
51 #include "whois.h"
52 #include "funny.h"
53 #include "parse.h"
54
55 #include "dma.h"
56 #include "ckey.h"
57 #include "bans.h"
58 #include "ninja.h"
59 #include "channels.h"
60 #include "nicks.h"
61
62 static void nickname_in_use _((u_char *, u_char **));
63 static void password_sendline _((u_char *, u_char *));
64 static void get_password _((void));
65 static void nickname_sendline _((u_char *, u_char *));
66 static void channel_topic _((u_char *, u_char **));
67 static void not_valid_channel _((u_char *, u_char **));
68 static void cannot_join_channel _((u_char *, u_char **));
69 static void version _((u_char *, u_char **));
70 static void invite _((u_char *, u_char **));
71
72 /* ninja extensions */
73 static void channel_topic_time _((u_char *, u_char **));
74 static void show_ban_except_line _((u_char *, u_char **));
75 extern u_char *old_nick;
76 u_char *leader = UNULL;
77
78 static int already_doing_reset_nickname = 0;
79
80 /*
81 * numeric_banner: This returns in a static string of either "xxx" where
82 * xxx is the current numeric, or "***" if SHOW_NUMBERS is OFF
83 */
84 u_char *
numeric_banner()85 numeric_banner()
86 {
87 static u_char thing[8];
88
89 if (get_string_var(LEADER_VAR) && !get_int_var(SHOW_NUMERICS_VAR))
90 return leader;
91
92 memset(thing, 0, sizeof(thing));
93 if (get_int_var(SHOW_NUMERICS_VAR))
94 snprintf(CP(thing), sizeof(thing)-1, "%3.3u ", -current_numeric);
95 else
96 my_strcpy(thing, "*** "); /* safe thing[8] */
97 return (thing);
98 }
99
100
101 /*
102 * display_msg: handles the displaying of messages from the variety of
103 * possible formats that the irc server spits out. you'd think someone would
104 * simplify this
105 */
106 void
display_msg(from,ArgList)107 display_msg(from, ArgList)
108 u_char *from,
109 **ArgList;
110 {
111 u_char *ptr;
112 u_char *rest;
113
114 rest = PasteArgs(ArgList, 0);
115 if (from && (my_strnicmp(get_server_itsname(parsing_server_index), from,
116 my_strlen(get_server_itsname(parsing_server_index))) == 0))
117 from = (u_char *) 0;
118 if ((ptr = (u_char *) my_index(rest, ':')) != NULL)
119 {
120 *(ptr++) = (u_char) 0;
121 if (my_strlen(rest))
122 {
123 if (from)
124 put_it("%s%s: %s (from %s)", numeric_banner(),
125 rest, ptr, from);
126 else
127 put_it("%s%s: %s", numeric_banner(), rest,
128 ptr);
129 }
130 else
131 {
132 if (from)
133 put_it("%s%s (from %s)", numeric_banner(),
134 ptr, from);
135 else
136 put_it("%s%s", numeric_banner(), ptr);
137 }
138 }
139 else
140 {
141 if (from)
142 put_it("%s%s (from %s)", numeric_banner(), rest, from);
143 else
144 put_it("%s%s", numeric_banner(), rest);
145 }
146 }
147
148 /*
149 * password_sendline: called by send_line() in get_password() to handle
150 * hitting of the return key, etc
151 */
152 static void
password_sendline(data,line)153 password_sendline(data, line)
154 u_char *data;
155 u_char *line;
156 {
157 int new_server;
158
159 new_server = my_atoi(data);
160 set_server_password(new_server, line);
161 connect_to_server(get_server_name(new_server),
162 get_server_port(new_server), get_server_nickname(new_server), -1);
163 }
164
165 /*
166 * get_password: when a host responds that the user needs to supply a
167 * password, it gets handled here! the user is prompted for a password and
168 * then reconnection is attempted with that password. but, the reality of
169 * the situation is that no one really uses user passwords. ah well
170 */
171 static void
get_password()172 get_password()
173 {
174 u_char server_num[8];
175
176 say("password required for connection to server %s",
177 get_server_name(parsing_server_index));
178 close_server(parsing_server_index, empty_string);
179 if (!dumb)
180 {
181 memset(server_num, 0, sizeof(server_num));
182 snprintf(CP(server_num), sizeof(server_num)-1, "%d", parsing_server_index);
183 add_wait_prompt(UP("Server Password:"), password_sendline,
184 server_num, WAIT_PROMPT_LINE);
185 }
186 }
187
188 /*ARGSUSED*/
189 static void
nickname_sendline(data,nick)190 nickname_sendline(data, nick)
191 u_char *data;
192 u_char *nick;
193 {
194 int new_server, server;
195
196 new_server = my_atoi(data);
197 server = parsing_server_index;
198 from_server = new_server;
199 send_to_server("NICK %s", nick);
200 if (new_server == primary_server)
201 malloc_strcpy(&nickname, nick);
202 set_server_nickname(new_server, nick);
203 from_server = server;
204 already_doing_reset_nickname = 0;
205 update_all_status();
206 }
207
208 /*
209 * reset_nickname: when the server reports that the selected nickname is not
210 * a good one, it gets reset here.
211 */
212 void
reset_nickname()213 reset_nickname()
214 {
215 u_char server_num[10];
216
217 if (already_doing_reset_nickname)
218 return;
219 say("You have specified an illegal nickname");
220 if (!dumb && !get_int_var(NO_ASK_NICKNAME_VAR))
221 {
222 already_doing_reset_nickname = 1;
223 say("Please enter your nickname");
224 sprintf(CP(server_num), "%d", parsing_server_index); /* somewhat safe, assumes %d < 19 */
225 add_wait_prompt(UP("Nickname: "), nickname_sendline, server_num,
226 WAIT_PROMPT_LINE);
227 }
228 update_all_status();
229 }
230
231 /*ARGSUSED*/
232 static void
channel_topic(from,ArgList)233 channel_topic(from, ArgList)
234 u_char *from,
235 **ArgList;
236 {
237 u_char *topic, *channel;
238
239 save_message_from();
240 if (ArgList[1] && is_channel(ArgList[0]))
241 {
242 topic = ArgList[1];
243 channel = ArgList[0];
244 message_from(channel, LOG_CRAP);
245 put_it("%sTopic for %s: %s", numeric_banner(), channel,
246 topic);
247 }
248 else
249 {
250 message_from((u_char *) 0, LOG_CURRENT); /* XXX should remove this */
251 PasteArgs(ArgList, 0);
252 put_it("%sTopic: %s", numeric_banner(), ArgList[0]);
253 }
254 restore_message_from();
255 }
256
257 static void
nickname_in_use(from,ArgList)258 nickname_in_use(from, ArgList)
259 u_char *from,
260 **ArgList;
261 {
262 PasteArgs(ArgList, 0);
263 if (is_server_connected(parsing_server_index)) {
264 if (do_hook(current_numeric, "%s", *ArgList))
265 display_msg(from, ArgList);
266 }
267 else
268 {
269 u_char *unp = UNULL;
270
271 if (never_connected || parsing_server_index != primary_server ||
272 !attempting_to_connect)
273 {
274 if (do_hook(current_numeric, "%s", *ArgList))
275 display_msg(from, ArgList);
276 /* reset_nickname(); */
277 }
278 else
279 {
280 send_to_server("USER %s %s ninja-%s :%s", username,
281 (send_umode && *send_umode) ? send_umode : (u_char *) ".",
282 irc_version,
283 realname);
284 }
285
286 unp = next_arg(*ArgList, ArgList);
287 if (unp)
288 rotate_nick(unp);
289 }
290 }
291
292
293 static void
not_valid_channel(from,ArgList)294 not_valid_channel(from, ArgList)
295 u_char *from,
296 **ArgList;
297 {
298 u_char *channel;
299 u_char *s;
300
301 if (!(channel = ArgList[0]) || !ArgList[1])
302 return;
303 PasteArgs(ArgList, 1);
304 s = get_server_name(parsing_server_index);
305 if (0 == my_strnicmp(s, from, my_strlen(s)))
306 {
307 /*
308 * lets not do this...
309 *
310 remove_channel(channel, parsing_server_index);
311 */
312 put_it("%s%s %s", numeric_banner(), channel, ArgList[1]);
313 }
314 }
315
316 /* from ircd .../include/numeric.h */
317 /*
318 #define ERR_CHANNELISFULL 471
319 #define ERR_INVITEONLYCHAN 473
320 #define ERR_BANNEDFROMCHAN 474
321 #define ERR_BADCHANNELKEY 475
322 #define ERR_BADCHANMASK 476
323 */
324 static void
cannot_join_channel(from,ArgList)325 cannot_join_channel(from, ArgList)
326 u_char *from,
327 **ArgList;
328 {
329 u_char chan[512], *keyp;
330 u_char buffer[BIG_BUFFER_SIZE];
331
332 if (!ArgList[0])
333 return;
334 my_strncpy(chan, ArgList[0], sizeof(chan)-1);
335 chan[sizeof(chan)-1] = '\0';
336
337 if (is_on_channel(chan, parsing_server_index, get_server_nickname(parsing_server_index)))
338 return;
339 remove_channel(chan, parsing_server_index);
340
341 PasteArgs(ArgList, 0);
342 if (do_hook(current_numeric, "%s %s", from, *ArgList)) {
343 my_strncpy(buffer, ArgList[0], sizeof(buffer)-1);
344 buffer[sizeof(buffer)-1] = '\0';
345 switch(-current_numeric)
346 {
347 case 471:
348 my_strmcat(buffer, " (Channel is full)", sizeof(buffer)-1);
349 break;
350 case 473:
351 my_strmcat(buffer, " (Invite only channel)", sizeof(buffer)-1);
352 break;
353 case 474:
354 my_strmcat(buffer, " (Banned from channel)", sizeof(buffer)-1);
355 break;
356 case 475:
357 my_strmcat(buffer, " (Bad channel key", sizeof(buffer)-1);
358 keyp = get_ckey(chan);
359 if (keyp && *keyp)
360 {
361 if (!get_int_var(HIDE_CHANNEL_KEYS_VAR))
362 {
363 my_strmcat(buffer, ": ", sizeof(buffer)-1);
364 my_strmcat(buffer, keyp, sizeof(buffer)-1);
365 }
366 else
367 my_strmcat(buffer, " (from key list)", sizeof(buffer)-1);
368 }
369 my_strmcat(buffer, ")", sizeof(buffer)-1);
370 break;
371 case 476:
372 my_strmcat(buffer, " (Bad channel mask)", sizeof(buffer)-1);
373 break;
374 }
375 put_it("%s%s", numeric_banner(), buffer);
376 }
377 }
378
379
380 /*ARGSUSED*/
381 static void
version(from,ArgList)382 version(from, ArgList)
383 u_char *from,
384 **ArgList;
385 {
386 if (ArgList[2])
387 {
388 PasteArgs(ArgList, 2);
389 put_it("%sServer %s: %s %s", numeric_banner(), ArgList[1],
390 ArgList[0], ArgList[2]);
391 }
392 else
393 {
394 PasteArgs(ArgList, 1);
395 put_it("%sServer %s: %s", numeric_banner(), ArgList[1],
396 ArgList[0]);
397 }
398 }
399
400
401 /*ARGSUSED*/
402 static void
invite(from,ArgList)403 invite(from, ArgList)
404 u_char *from,
405 **ArgList;
406 {
407 u_char *who,
408 *channel;
409
410 if ((who = ArgList[0]) && (channel = ArgList[1]))
411 {
412 save_message_from();
413 message_from(channel, LOG_CRAP);
414 if (do_hook(current_numeric, "%s %s %s", from, who, channel))
415 put_it("%sInviting %s to %s",
416 numeric_banner(), who, channel);
417 restore_message_from();
418 }
419 }
420
421
422 /*
423 * numbered_command: does (hopefully) the right thing with the numbered
424 * responses from the server. I wasn't real careful to be sure I got them
425 * all, but the default case should handle any I missed (sorry)
426 */
427 void
numbered_command(from,comm,ArgList)428 numbered_command(from, comm, ArgList)
429 u_char *from;
430 int comm;
431 u_char **ArgList;
432 {
433 u_char *user;
434 u_char none_of_these = 0;
435 u_char blah[BIG_BUFFER_SIZE];
436 int flag,
437 lastlog_level;
438 #if 0
439 int user_cnt,
440 inv_cnt,
441 server_cnt;
442 #endif /* 0 */
443
444 if (!from || !*from)
445 return;
446 if (!*ArgList[0])
447 user = (u_char *) 0;
448 else
449 user = ArgList[0];
450 if (!ArgList[1])
451 return;
452 lastlog_level = set_lastlog_msg_level(LOG_CRAP);
453 save_message_from();
454 message_from((u_char *) 0, LOG_CRAP);
455 ArgList++;
456 current_numeric = -comm; /* must be negative of numeric! */
457 switch (comm)
458 {
459 case 001: /* #define RPL_WELCOME 001 */
460 /*
461 * always take the nick from this line!
462 */
463 if (user)
464 set_server_nickname(from_server, user);
465 else if (old_nick)
466 {
467 set_server_nickname(from_server, old_nick);
468 dma_Free(&old_nick);
469 }
470 /* lets also set the server's user mode here */
471 if (server_list[from_server].usermode)
472 send_to_server("MODE %s %s",
473 server_list[from_server].nickname,
474 server_list[from_server].usermode);
475
476 PasteArgs(ArgList, 0);
477 if (do_hook(current_numeric, "%s %s", from, *ArgList))
478 display_msg(from, ArgList);
479 clean_whois_queue();
480 break;
481 case 002: /* #define RPL_YOURHOST 002 */
482 PasteArgs(ArgList, 0);
483 sprintf(CP(blah), "*** %s", ArgList[0]);
484 got_initial_version(blah);
485 if (do_hook(current_numeric, "%s %s", from, *ArgList))
486 display_msg(from, ArgList);
487 break;
488
489 /* should do something with this some day, 2.8 had channel/user mode switches
490 *
491 * this is now handled by nincache.c also (the channel/user modes)
492 */
493 case 004: /* #define RPL_MYINFO 004 */
494 PasteArgs(ArgList, 0);
495 if (do_hook(current_numeric, "%s %s", from, *ArgList))
496 display_msg(from, ArgList);
497 break;
498
499 /*
500 * this part of ircii has been broken for most of ircd 2.7, so someday I'll
501 * make it work for ircd 2.8 ... phone..
502 */
503 #if 0
504 case 251: /* #define RPL_LUSERCLIENT 251 */
505 display_msg(from, ArgList);
506 if (server_list[from_server].connected)
507 break;
508 if ((from_server == primary_server) && ((sscanf(ArgList[1],
509 "There are %d users and %d invisible on %d servers",
510 &user_cnt, &inv_cnt, &server_cnt) == 3)||(sscanf(ArgList[1],
511 "There are %d users and %d invisible on %d servers",
512 &user_cnt, &inv_cnt, &server_cnt) == 3)))
513 {
514 user_cnt += inv_cnt;
515 if ((server_cnt < get_int_var(MINIMUM_SERVERS_VAR)) ||
516 (user_cnt < get_int_var(MINIMUM_USERS_VAR)))
517 {
518 say("Trying better populated server...");
519 get_connected(from_server + 1);
520 }
521 }
522 break;
523 #endif /* 0 */
524 case 301: /* #define RPL_AWAY 301 */
525 user_is_away(from, ArgList);
526 break;
527
528 case 302: /* #define RPL_USERHOST 302 */
529 userhost_returned(from, ArgList);
530 break;
531
532 case 303: /* #define RPL_ISON 303 */
533 ison_returned(from, ArgList);
534 break;
535
536 case 311: /* #define RPL_WHOISUSER 311 */
537 whois_name(from, ArgList);
538 break;
539
540 case 312: /* #define RPL_WHOISSERVER 312 */
541 whois_server(from, ArgList);
542 break;
543
544 case 313: /* #define RPL_WHOISOPERATOR 313 */
545 whois_oper(from, ArgList);
546 break;
547
548 case 314: /* #define RPL_WHOWASUSER 314 */
549 whowas_name(from, ArgList);
550 break;
551
552 case 316: /* #define RPL_WHOISCHANOP 316 */
553 whois_chop(from, ArgList);
554 break;
555
556 case 317: /* #define RPL_WHOISIDLE 317 */
557 whois_lastcom(from, ArgList);
558 break;
559
560 case 318: /* #define RPL_ENDOFWHOIS 318 */
561 end_of_whois(from, ArgList);
562 break;
563
564 case 319: /* #define RPL_WHOISCHANNELS 319 */
565 whois_channels(from, ArgList);
566 break;
567
568 case 321: /* #define RPL_LISTSTART 321 */
569 ArgList[0] = UP("Channel\0Users\0Topic");
570 ArgList[1] = ArgList[0] + 8;
571 ArgList[2] = ArgList[1] + 6;
572 ArgList[3] = (u_char *) 0;
573 funny_list(from, ArgList);
574 break;
575
576 case 322: /* #define RPL_LIST 322 */
577 funny_list(from, ArgList);
578 break;
579
580 case 324: /* #define RPL_CHANNELMODEIS 324 */
581 {
582 Channel *tc;
583 if (ArgList[0]
584 && (tc = lookup_channel(ArgList[0], from_server, CHAN_NOUNLINK))
585 && (tc->status & CHAN_MODE))
586 funny_mode(from, ArgList);
587 }
588 break;
589
590 case 329: /* #define RPL_CREATIONTIME 329 */
591 {
592 if (ArgList[1])
593 {
594 time_t t;
595
596 sscanf(ArgList[1], "%lu", &t); /* XXX: not a good idea.. str_to_time_t is needed or something */
597 save_message_from();
598 message_from(ArgList[0], LOG_CRAP);
599 if (do_hook(current_numeric, "%s %s %s", from, ArgList[0], ArgList[1]))
600 put_info("%s was created %s", ArgList[0],
601 ninja_strftime(&t, "%a, %b %d at %I:%M%p"));
602 restore_message_from();
603 }
604 }
605 break;
606
607 case 341: /* #define RPL_INVITING 341 */
608 invite(from, ArgList);
609 break;
610
611 case 348: /* #define RPL_EXCEPTLIST 348 */
612 if (ArgList[0])
613 show_ban_except_line(from, ArgList);
614 break;
615 case 349: /* #define RPL_ENDOFEXCEPTLIST 349 */
616 if (ArgList[0])
617 {
618 PasteArgs(ArgList, 0);
619 flag = do_hook(current_numeric, "%s %s", from, ArgList[0]);
620 if (get_int_var(SHOW_END_OF_MSGS_VAR) && flag)
621 display_msg(from, ArgList);
622 }
623 break;
624
625 case 352: /* #define RPL_WHOREPLY 352 */
626 whoreply((u_char *) 0, ArgList);
627 break;
628
629 case 353: /* #define RPL_NAMREPLY 353 */
630 funny_namreply(from, ArgList);
631 break;
632
633 case 366: /* #define RPL_ENDOFNAMES 366 */
634 {
635 u_char *tmp = (u_char *) 0,
636 *chan;
637
638 malloc_strcpy(&tmp, ArgList[0]);
639 chan = tmp;
640 PasteArgs(ArgList, 0);
641 /* chan = UP(strtok(CP(tmp), " ")); */
642 flag = do_hook(current_numeric, "%s %s", from, ArgList[0]);
643 if (get_int_var(SHOW_END_OF_MSGS_VAR) && flag)
644 display_msg(from, ArgList);
645
646 new_free(&tmp);
647 }
648 break;
649
650 case 367: /* #define RPL_BANLIST 367 */
651 if (ArgList[0])
652 show_ban_except_line(from, ArgList);
653 break;
654 case 368: /* #define RPL_ENDOFBANLIST 368 */
655 if (ArgList[0])
656 {
657 PasteArgs(ArgList, 0);
658 flag = do_hook(current_numeric, "%s %s", from, ArgList[0]);
659 if (get_int_var(SHOW_END_OF_MSGS_VAR) && flag)
660 display_msg(from, ArgList);
661 }
662 break;
663
664 case 381: /* #define RPL_YOUREOPER 381 */
665 PasteArgs(ArgList, 0);
666 if (do_hook(current_numeric, "%s %s", from, *ArgList))
667 display_msg(from, ArgList);
668 set_server_operator(parsing_server_index, 1);
669 update_all_status(); /* fix the status line */
670 break;
671
672 case 401: /* #define ERR_NOSUCHNICK 401 */
673 no_such_nickname(from, ArgList);
674 break;
675
676 case 405: /* #define ERR_TOOMANYCHANNELS 405 */
677 remove_channel(ArgList[0], parsing_server_index);
678 break;
679
680 case 421: /* #define ERR_UNKNOWNCOMMAND 421 */
681 if (check_screen_redirect(ArgList[0]))
682 break;
683 if (check_wait_command(ArgList[0]))
684 break;
685 PasteArgs(ArgList, 0);
686 flag = do_hook(current_numeric, "%s %s", from, *ArgList);
687 if (!my_strncmp("ISON", *ArgList, 4) || !my_strncmp("USERHOST",
688 *ArgList, 8))
689 {
690 set_server_2_6_2(parsing_server_index, 0);
691 convert_to_whois();
692 }
693 else if (flag)
694 display_msg(from, ArgList);
695 break;
696
697 case 432: /* #define ERR_ERRONEUSNICKNAME 432 */
698 if (do_hook(current_numeric, "%s %s", from, *ArgList))
699 {
700 u_char *enp;
701
702 display_msg(from, ArgList);
703 enp = next_arg(*ArgList, ArgList);
704 if (enp)
705 rotate_nick(enp);
706 }
707 break;
708
709 case 433: /* #define ERR_NICKNAMEINUSE 433 */
710 if (!attempting_to_connect
711 && get_int_var(AUTO_WHOIS_NICK_IN_USE_VAR))
712 send_to_server("WHOIS %s", ArgList[0]);
713 nickname_in_use(from, ArgList);
714 break;
715
716 case 437: /* #define ERR_UNAVAILRESOURCE 437 */
717 flag = do_hook(current_numeric, "%s %s", from, *ArgList);
718 if (!is_channel(*ArgList))
719 {
720 nickname_in_use(from, ArgList);
721 /* reset_nickname(); */
722 } else if (flag)
723 display_msg(from, ArgList);
724 break;
725
726
727
728 case 463: /* #define ERR_NOPERMFORHOST 463 */
729 display_msg(from, ArgList);
730 close_server(parsing_server_index, empty_string);
731 window_check_servers();
732 if (!connected_to_server
733 && get_int_var(AUTO_RECONNECT_VAR))
734 get_connected(parsing_server_index + 1);
735 break;
736
737 case 464: /* #define ERR_PASSWDMISMATCH 464 */
738 PasteArgs(ArgList, 0);
739 flag = do_hook(current_numeric, "%s %s", from, ArgList[0]);
740 if (oper_command)
741 {
742 if (flag)
743 display_msg(from, ArgList);
744 }
745 else
746 get_password();
747 break;
748
749 case 465: /* #define ERR_YOUREBANNEDCREEP 465 */
750 {
751 int klined_server = parsing_server_index;
752
753 PasteArgs(ArgList, 0);
754 if (do_hook(current_numeric, "%s %s", from, ArgList[0]))
755 display_msg(from, ArgList);
756 close_server(parsing_server_index, empty_string);
757 window_check_servers();
758 if (number_of_servers > 1)
759 {
760 remove_from_server_list(klined_server);
761 }
762 if (!connected_to_server
763 && get_int_var(AUTO_RECONNECT_VAR))
764 get_connected(klined_server + 1);
765 /* say("You are not connected to a server. Use /SERVER to connect."); */
766 break;
767 }
768
769 case 471: /* #define ERR_CHANNELISFULL 471 */
770 case 473: /* #define ERR_INVITEONLYCHAN 473 */
771 case 474: /* #define ERR_BANNEDFROMCHAN 474 */
772 case 475: /* #define ERR_BADCHANNELKEY 475 */
773 case 476: /* #define ERR_BADCHANMASK 476 */
774 cannot_join_channel(from, ArgList);
775 break;
776
777 case 484: /* #define ERR_RESTRICTED 484 */
778 if (do_hook(current_numeric, "%s %s", from, *ArgList))
779 display_msg(from, ArgList);
780 set_server_flag(parsing_server_index, USER_MODE_R, 1);
781 break;
782
783 /*
784 * The following accumulates the remaining arguments
785 * in ArgSpace for hook detection. We can't use
786 * PasteArgs here because we still need the arguments
787 * separated for use elsewhere.
788 */
789 default:
790 {
791 u_char *ArgSpace = (u_char *) 0;
792 int i,
793 do_message_from = 0;
794 size_t len;
795
796 for (i = len = 0; ArgList[i]; len += my_strlen(ArgList[i++]))
797 ;
798 len += (i - 1);
799 ArgSpace = new_malloc(len + 1);
800 ArgSpace[0] = '\0';
801 /* this is cheating */
802 if (ArgList[0] && is_channel(ArgList[0]))
803 do_message_from = 1;
804 for (i = 0; ArgList[i]; i++)
805 {
806 if (i)
807 my_strcat(ArgSpace, " ");
808 my_strcat(ArgSpace, ArgList[i]);
809 }
810 if (do_message_from)
811 message_from(ArgList[0], LOG_CRAP);
812 i = do_hook(current_numeric, "%s %s", from, ArgSpace);
813 new_free(&ArgSpace);
814 if (do_message_from)
815 restore_message_from();
816 if (i == 0)
817 goto done;
818 none_of_these = 1;
819 }
820 }
821 /* the following do not hurt the ircII if intercepted by a hook */
822 if (none_of_these)
823 {
824 switch (comm)
825 {
826 case 221: /* #define RPL_UMODEIS 221 */
827 put_it("%sYour user mode is \"%s\"", numeric_banner(),
828 ArgList[0]);
829 break;
830
831 case 242: /* #define RPL_STATSUPTIME 242 */
832 PasteArgs(ArgList, 0);
833 if (from && !my_strnicmp(get_server_itsname(parsing_server_index),
834 from, my_strlen(get_server_itsname(parsing_server_index))))
835 from = NULL;
836 if (from)
837 put_it("%s%s from (%s)", numeric_banner(),
838 *ArgList, from);
839 else
840 put_it("%s%s", numeric_banner(), *ArgList);
841 break;
842
843 case 332: /* #define RPL_TOPIC 332 */
844 channel_topic(from, ArgList);
845 break;
846
847 case 333: /* #define RPL_TOPICWHOTIME 333 */
848 channel_topic_time(from, ArgList);
849 break;
850
851 case 351: /* #define RPL_VERSION 351 */
852 version(from, ArgList);
853 break;
854
855 case 364: /* #define RPL_LINKS 364 */
856 if (ArgList[2])
857 {
858 PasteArgs(ArgList, 2);
859 put_it("%s%-20s %-20s %s", numeric_banner(),
860 ArgList[0], ArgList[1], ArgList[2]);
861 }
862 else
863 {
864 PasteArgs(ArgList, 1);
865 put_it("%s%-20s %s", numeric_banner(),
866 ArgList[0], ArgList[1]);
867 }
868 break;
869
870 case 372: /* #define RPL_MOTD 372 */
871 if (!get_int_var(SUPPRESS_SERVER_MOTD_VAR) ||
872 !get_server_motd(parsing_server_index))
873 {
874 PasteArgs(ArgList, 0);
875 put_it("%s%s", numeric_banner(), ArgList[0]);
876 }
877 break;
878
879 case 375: /* #define RPL_MOTDSTART 375 */
880 if (!get_int_var(SUPPRESS_SERVER_MOTD_VAR) ||
881 !get_server_motd(parsing_server_index))
882 {
883 PasteArgs(ArgList, 0);
884 put_it("%s%s", numeric_banner(), ArgList[0]);
885 }
886 break;
887
888 case 376: /* #define RPL_ENDOFMOTD 376 */
889 if (attempting_to_connect)
890 got_initial_version(UP("*** Your host is broken and not running any version"));
891 if (get_int_var(SHOW_END_OF_MSGS_VAR) &&
892 (!get_int_var(SUPPRESS_SERVER_MOTD_VAR) ||
893 !get_server_motd(parsing_server_index)))
894 {
895 PasteArgs(ArgList, 0);
896 put_it("%s%s", numeric_banner(), ArgList[0]);
897 }
898 set_server_motd(parsing_server_index, 0);
899 break;
900
901 case 384: /* #define RPL_MYPORTIS 384 */
902 PasteArgs(ArgList, 0);
903 put_it("%s%s %s", numeric_banner(), ArgList[0], user);
904 break;
905
906 case 385: /* #define RPL_NOTOPERANYMORE 385 */
907 set_server_operator(parsing_server_index, 0);
908 display_msg(from, ArgList);
909 update_all_status();
910 break;
911
912 case 403: /* #define ERR_NOSUCHCHANNEL 403 */
913 not_valid_channel(from, ArgList);
914 break;
915
916 case 432: /* #define ERR_ERRONEUSNICKNAME 432 */
917 display_msg(from, ArgList);
918 /* reset_nickname(); 8*/
919 break;
920
921 case 451: /* #define ERR_NOTREGISTERED 451 */
922 /*
923 * Sometimes the server doesn't catch the USER line, so
924 * here we send a simplified version again -lynx
925 */
926 send_to_server("USER %s %s ninja-%s :%s", username,
927 (send_umode && *send_umode) ? send_umode : (u_char *) ".",
928 irc_version,
929 realname);
930 send_to_server("NICK %s",
931 get_server_nickname(parsing_server_index));
932 break;
933
934 case 462: /* #define ERR_ALREADYREGISTRED 462 */
935 display_msg(from, ArgList);
936 break;
937
938 #define RPL_CLOSEEND 363
939 #define RPL_SERVLISTEND 235
940 case 315: /* #define RPL_ENDOFWHO 315 */
941 if (cannot_open != (u_char *) 0)
942 yell("Cannot open: %s", cannot_open);
943
944 case 323: /* #define RPL_LISTEND 323 */
945 funny_print_widelist();
946
947 case 219: /* #define RPL_ENDOFSTATS 219 */
948 case 232: /* #define RPL_ENDOFSERVICES 232 */
949 case 365: /* #define RPL_ENDOFLINKS 365 */
950 case 369: /* #define RPL_ENDOFWHOWAS 369 */
951 case 374: /* #define RPL_ENDOFINFO 374 */
952 #if 0 /* this case needs special handing - see above */
953 case 376: /* #define RPL_ENDOFMOTD 376 */
954 #endif /* 0 */
955 case 394: /* #define RPL_ENDOFUSERS 394 */
956 if (!get_int_var(SHOW_END_OF_MSGS_VAR))
957 break;
958 default:
959 display_msg(from, ArgList);
960 }
961 }
962 set_lastlog_msg_level(lastlog_level);
963 done:
964 restore_message_from();
965 }
966
967
968 /*
969 * show a ban/ban exception on a channel..
970 */
971 static void
show_ban_except_line(from,ArgList)972 show_ban_except_line(from, ArgList)
973 u_char *from, **ArgList;
974 {
975 if (is_channel(ArgList[0]) && ArgList[1])
976 {
977 if (ArgList[2] && ArgList[3])
978 {
979 time_t t;
980
981 sscanf(ArgList[3], "%lu", (unsigned long *) &t);
982 put_info("[%s] %s by %s at %s", ArgList[0], ArgList[1], ArgList[2], ninja_strftime(&t, "%I:%M%p on %a, %b %d"));
983 }
984 else if (ArgList[2])
985 put_info("[%s] %s by %s", ArgList[0], ArgList[1], ArgList[2]);
986 else
987 put_info("[%s] %s", ArgList[0], ArgList[1]);
988 }
989 }
990
991 /*
992 * when the topic got set and who set it
993 */
994 static void
channel_topic_time(from,ArgList)995 channel_topic_time(from, ArgList)
996 u_char *from, **ArgList;
997 {
998 if (ArgList[1] && is_channel(ArgList[0]) && ArgList[2])
999 {
1000 time_t t;
1001
1002 message_from(ArgList[0], LOG_CRAP);
1003 sscanf(ArgList[2], "%lu", (unsigned long *) &t);
1004 if (checkgrep(ArgList[0], NULL))
1005 put_raw("%sThe topic was set by %s on %s.", numeric_banner(),
1006 ArgList[1], ninja_strftime(&t, "%a, %b %d at %I:%M%p"));
1007
1008 }
1009 else
1010 {
1011 PasteArgs(ArgList, 0);
1012 message_from((char *) 0, LOG_CURRENT);
1013 put_raw("%sBroken RPL_TOPICWHOTIME: %s", numeric_banner(), *ArgList);
1014 }
1015 }
1016
1017