1 /*
2 * parse.c: handles messages from the server. Believe it or not. I
3 * certainly wouldn't if I were you.
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 #include "dma.h"
38 IRCII_RCSID("@(#)$Id: parse.c,v 1.76 2000/04/04 03:10:57 mrg Exp $");
39
40 #include "server.h"
41
42 #include "vars.h"
43 #include "ctcp.h"
44 #include "hook.h"
45 #include "edit.h"
46 #include "ignore.h"
47 #include "whois.h"
48 #include "lastlog.h"
49 #include "ircaux.h"
50 #include "funny.h"
51 #include "irccrypt.h"
52 #include "ircterm.h"
53 #include "flood.h"
54 #include "window.h"
55 #include "screen.h"
56 #include "output.h"
57 #include "numbers.h"
58 #include "parse.h"
59 #include "notify.h"
60
61 #include "channels.h"
62 #include "ninja.h"
63 #include "nincache.h"
64 #include "tabkey.h"
65 #include "ninredir.h"
66 #include "orignick.h"
67
68 /*
69 * moved to channels.c
70 *
71 #define STRING_CHANNEL '+'
72 #define MULTI_CHANNEL '#'
73 #define LOCAL_CHANNEL '&'
74 #define SAFE_CHANNEL '!'
75 */
76
77 /*
78 * moved to parse.h:
79 *
80 #define MAXPARA 15 / * Taken from the ircd * /
81 *
82 *
83 static void BreakArgs _((u_char *, u_char **, u_char **));
84 */
85
86 static void p_linreply _((u_char **));
87 /* static void p_ping _((u_char **)); */
88 static void p_topic _((u_char *, u_char **));
89 static void p_wall _((u_char *, u_char **));
90 static void p_wallops _((u_char *, u_char **));
91 static void p_privmsg _((u_char *, u_char **));
92 /*static void p_msgcmd _((u_char *, u_char **));*/
93 static void p_quit _((u_char *, u_char **));
94 static void p_pong _((u_char *, u_char **));
95 static void p_error _((u_char *, u_char **));
96 static void p_channel _((u_char *, u_char **));
97 static void p_invite _((u_char *, u_char **));
98 static void p_server_kill _((u_char *, u_char **));
99 static void p_nick _((u_char *, u_char **, int, u_char *));
100 static void p_mode _((u_char *, u_char **));
101 static void p_kick _((u_char *, u_char **));
102 static void p_part _((u_char *, u_char **));
103
104 /*
105 * joined_nick: the nickname of the last person who joined the current
106 * channel
107 */
108 u_char *joined_nick = (u_char *) 0;
109
110 /* public_nick: nick of the last person to send a message to your channel */
111 u_char *public_nick = (u_char *) 0;
112
113 /* User and host information from server 2.7 */
114 u_char *FromUserHost = (u_char *) 0;
115
116 /* ninja likes them seperated too */
117 u_char *FromUser = UNULL;
118 u_char *FromHost = UNULL;
119
120 /* doing a PRIVMSG */
121 int doing_privmsg = 0;
122
123 /*
124 *
125 * THIS WAS MOVED TO CHANNELS.C WHERE IT BELONGS
126 *
127 * is_channel: determines if the argument is a channel. If it's a number,
128 * begins with MULTI_CHANNEL and has no '*', or STRING_CHANNEL, then its a
129 * channel.
130 *
131 int
132 is_channel(to)
133 u_char *to;
134 {
135 int version;
136
137 if (to == 0)
138 return (0);
139
140 version = get_server_version(from_server);
141 return ((version < Server2_7 && (isdigit(*to) || (*to == STRING_CHANNEL)
142 || *to == '-'))
143 || (version > Server2_5 && *to == MULTI_CHANNEL)
144 || (version > Server2_7 && *to == LOCAL_CHANNEL)
145 || (version > Server2_8 && *to == STRING_CHANNEL)
146 || (version > Server2_9 && *to == SAFE_CHANNEL)
147 || (version == ServerICB && my_stricmp(to, get_server_icbgroup(from_server)) == 0));
148 }
149 *
150 */
151
152 u_char *
PasteArgs(Args,StartPoint)153 PasteArgs(Args, StartPoint)
154 u_char **Args;
155 int StartPoint;
156 {
157 int i;
158
159 for (; StartPoint; Args++, StartPoint--)
160 if (!*Args)
161 return (u_char *) 0;
162 for (i = 0; Args[i] && Args[i+1]; i++)
163 Args[i][my_strlen(Args[i])] = ' ';
164 Args[1] = (u_char *) 0;
165 return Args[0];
166 }
167
168 /*
169 * BreakArgs: breaks up the line from the server, in to where its from,
170 * setting FromUserHost if it should be, and returns all the arguements
171 * that are there. Re-written by phone, dec 1992.
172 */
173 void
BreakArgs(Input,Sender,OutPut)174 BreakArgs(Input, Sender, OutPut)
175 u_char *Input;
176 u_char **Sender;
177 u_char **OutPut;
178 {
179 u_char *s = Input,
180 *t;
181 int ArgCount = 0;
182
183 /*
184 * Get sender from :sender and user@host if :nick!user@host
185 */
186 dma_Free(&FromUserHost);
187 dma_Free(&FromUser);
188 dma_Free(&FromHost);
189
190 if (*Input == ':')
191 {
192 u_char *tmp;
193
194 *Input++ = '\0';
195 if ((s = (u_char *) my_index(Input, ' ')) != (u_char *) 0)
196 *s++ = '\0';
197 *Sender = Input;
198 if ((tmp = (u_char *) my_index(*Sender, '!')) != (u_char *) 0)
199 {
200 *tmp++ = '\0';
201 dma_strcpy(&FromUserHost, tmp);
202
203 /* save the user and host vars too */
204 t = my_index(FromUserHost, '@');
205 if (t)
206 {
207 /* well it modifies it... */
208 *t = '\0';
209 dma_strcpy(&FromUser, FromUserHost);
210 /* but it puts it back! */
211 *t++ = '@';
212 dma_strcpy(&FromHost, t);
213 }
214
215 }
216 }
217 else
218 *Sender = empty_string;
219
220 if (!s)
221 return;
222
223 for (;;)
224 {
225 while (*s == ' ')
226 *s++ = '\0';
227
228 if (!*s)
229 break;
230
231 if (*s == ':')
232 {
233 for (t = s; *t; t++)
234 *t = *(t + 1);
235 OutPut[ArgCount++] = s;
236 break;
237 }
238 OutPut[ArgCount++] = s;
239 if (ArgCount >= MAXPARA)
240 break;
241
242 for (; *s != ' ' && *s; s++)
243 ;
244 }
245 OutPut[ArgCount] = (u_char *) 0;
246 }
247
248 /* beep_em: Not hard to figure this one out */
249 void
beep_em(beeps)250 beep_em(beeps)
251 int beeps;
252 {
253 int cnt,
254 i;
255
256 for (cnt = beeps, i = 0; i < cnt; i++)
257 term_beep();
258 }
259
260 /* in response to a TOPIC message from the server */
261 static void
p_topic(from,ArgList)262 p_topic(from, ArgList)
263 u_char *from,
264 **ArgList;
265 {
266 int flag, ch_flag = !IGNORED;
267
268 if (!from)
269 return;
270 flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
271 if (ArgList[1])
272 ch_flag = double_ignore(ArgList[0], NULL, IGNORE_CRAP);
273 if (flag == IGNORED || ch_flag == IGNORED)
274 return;
275
276 save_message_from();
277 if (!ArgList[1])
278 {
279 message_from((u_char *) 0, LOG_CRAP);
280 if (do_hook(TOPIC_LIST, "%s * %s", from, ArgList[0]))
281 {
282 if (my_strlen(ArgList[0]) >= 1)
283 say("%s has changed the topic to %s", from, ArgList[0]);
284 else
285 say("%s has removed the topic", from);
286 }
287 }
288 else
289 {
290 message_from(ArgList[0], LOG_CRAP);
291 if (do_hook(TOPIC_LIST, "%s %s %s", from, ArgList[0], ArgList[1]))
292 {
293 if (my_strlen(ArgList[1]) >= 1)
294 say("%s has changed the topic on channel %s to %s",
295 from, ArgList[0], ArgList[1]);
296 else
297 say("%s has removed the topic on channel %s",
298 from, ArgList[0]);
299 }
300 }
301 restore_message_from();
302 }
303
304 static void
p_linreply(ArgList)305 p_linreply(ArgList)
306 u_char **ArgList;
307 {
308 PasteArgs(ArgList, 0);
309 say("%s", ArgList[0]);
310 }
311
312 static void
p_wall(from,ArgList)313 p_wall(from, ArgList)
314 u_char *from,
315 **ArgList;
316 {
317 int flag,
318 level;
319 u_char *line;
320 u_char *high;
321
322 if (!from)
323 return;
324 PasteArgs(ArgList, 0);
325 if (!(line = ArgList[0]))
326 return;
327 flag = double_ignore(from, FromUserHost, IGNORE_WALLS);
328 save_message_from();
329 message_from(from, LOG_WALL);
330 if (flag != IGNORED)
331 {
332 if (flag == HIGHLIGHTED)
333 high = &highlight_char;
334 else
335 high = empty_string;
336 if ((flag != DONT_IGNORE) && (ignore_usernames & IGNORE_WALLS)
337 && !FromUserHost)
338 add_to_whois_queue(from, whois_ignore_walls, "%s",line);
339 else
340 {
341 level = set_lastlog_msg_level(LOG_WALL);
342 if (check_flooding(from, WALL_FLOOD, line) &&
343 do_hook(WALL_LIST, "%s %s", from, line))
344 put_it("%s#%s#%s %s", high, from, high, line);
345 if (beep_on_level & LOG_WALL)
346 beep_em(1);
347 set_lastlog_msg_level(level);
348 }
349 }
350 restore_message_from();
351 }
352
353 static void
p_wallops(from,ArgList)354 p_wallops(from, ArgList)
355 u_char *from,
356 **ArgList;
357 {
358 int flag, level;
359 u_char *line;
360
361 if (!from)
362 return;
363 if (!(line = PasteArgs(ArgList, 0)))
364 return;
365 flag = double_ignore(from, FromUserHost, IGNORE_WALLOPS);
366 level = set_lastlog_msg_level(LOG_WALLOP);
367 save_message_from();
368 message_from(from, LOG_WALLOP);
369 if (my_index(from, '.'))
370 {
371 u_char *high;
372
373 if (flag != IGNORED)
374 {
375 if (flag == HIGHLIGHTED)
376 high = &highlight_char;
377 else
378 high = empty_string;
379 if (do_hook(WALLOP_LIST, "%s S %s", from, line))
380 put_it("%s!%s!%s %s", high, from, high, line);
381 if (beep_on_level & LOG_WALLOP)
382 beep_em(1);
383 }
384 }
385 else
386 {
387 if (get_int_var(USER_WALLOPS_VAR))
388 {
389 if ((flag != DONT_IGNORE) && (check_flooding(from, WALLOP_FLOOD, line)))
390 add_to_whois_queue(from, whois_new_wallops, "%s", line);
391 }
392 else if (my_strcmp(from, get_server_nickname(get_window_server(0))) != 0)
393 put_it("!%s! %s", from, line);
394 }
395 set_lastlog_msg_level(level);
396 restore_message_from();
397 }
398
399 /*ARGSUSED*/
400 void
whoreply(from,ArgList)401 whoreply(from, ArgList)
402 u_char **ArgList,
403 *from;
404 {
405 static u_char format[64];
406 static int last_width = -1;
407 static int showhops = -1;
408 int ok = 1;
409 u_char *channel,
410 *user,
411 *host,
412 *server,
413 *nick,
414 *status,
415 *name,
416 *hops;
417 int i;
418
419 FILE *fip;
420 u_char buf_data[BUFSIZ];
421
422 if (showhops != get_int_var(SHOW_WHO_HOPCOUNT_VAR))
423 showhops = get_int_var(SHOW_WHO_HOPCOUNT_VAR);
424
425 if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR))
426 {
427 if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0)
428 {
429 snprintf(CP(format), sizeof(format)-1,
430 "%%-%u.%us %%-9s |%%-3s",
431 (u_char) last_width,
432 (u_char) last_width);
433 format[sizeof(format)-1] = '\0';
434 }
435 else
436 my_strmcpy(format, "%s\t%-9s |%-3s", sizeof(format)-1);
437 if (showhops)
438 my_strmcat(format, " %2s", sizeof(format)-1);
439 my_strmcat(format, "|", sizeof(format)-1);
440 my_strmcat(format, " %s@%s (%s)", sizeof(format)-1);
441 }
442 i = 0;
443 channel = user = host = server = nick = status = name = hops = empty_string;
444 if (ArgList[i])
445 channel = ArgList[i++];
446 if (ArgList[i])
447 user = ArgList[i++];
448 if (ArgList[i])
449 host = ArgList[i++];
450 if (ArgList[i])
451 server = ArgList[i++];
452 if (ArgList[i])
453 nick = ArgList[i++];
454 if (ArgList[i])
455 status = ArgList[i++];
456 PasteArgs(ArgList, i);
457
458 if (*status == 'S') /* this only true for the header WHOREPLY */
459 {
460 channel = UP("Channel");
461 if (((who_mask & WHO_FILE) == 0) || (fopen (CP(who_file), "r")))
462 {
463 if (do_hook(WHO_LIST, "%s %s %s %s %s %s", channel,
464 nick, status, user, host, ArgList[6]))
465 {
466 if (showhops)
467 put_it(CP(format), channel, nick, status, UP(" #"), user,
468 host, ArgList[6]);
469 else
470 put_it(CP(format), channel, nick, status, user,
471 host, ArgList[6]);
472 return;
473 }
474 }
475 }
476
477 if (ArgList[i])
478 name = ArgList[i];
479 if (*name == ':')
480 name++;
481 if (isdigit(*name) && my_index(name, ' '))
482 hops = next_arg(name, &name);
483
484
485 if (who_mask)
486 {
487 if (who_mask & WHO_HERE)
488 ok = ok && (*status == 'H');
489 if (who_mask & WHO_AWAY)
490 ok = ok && (*status == 'G');
491 if (who_mask & WHO_OPS)
492 ok = ok && (*(status + 1) == '*');
493 if (who_mask & WHO_LUSERS)
494 ok = ok && (*(status + 1) != '*');
495 if (who_mask & WHO_CHOPS)
496 ok = ok && ((*(status + 1) == '@') ||
497 (*(status + 2) == '@'));
498 if (who_mask & WHO_NAME)
499 ok = ok && wild_match(who_name, user);
500 if (who_mask & WHO_NICK)
501 ok = ok && wild_match(who_nick, nick);
502 if (who_mask & WHO_HOST)
503 ok = ok && wild_match(who_host, host);
504 if (who_mask & WHO_REAL)
505 ok = ok && wild_match(who_real, name);
506 if (who_mask & WHO_SERVER)
507 ok = ok && wild_match(who_server, server);
508 if (who_mask & WHO_FILE)
509 {
510 ok = 0;
511 cannot_open = (u_char *) 0;
512 if ((fip = fopen(CP(who_file), "r")) != (FILE *) 0)
513 {
514 while (fgets ((char *)buf_data, BUFSIZ, fip) !=
515 (char *) 0)
516 {
517 buf_data[my_strlen(buf_data)-1] = '\0';
518 ok = ok || wild_match(buf_data, nick);
519 }
520 fclose (fip);
521 } else
522 cannot_open = who_file;
523 }
524 }
525 if (ok)
526 {
527 if (do_hook(WHO_LIST, "%s %s %s %s %s %s", channel, nick,
528 status, user, host, name))
529 {
530 if (showhops)
531 put_it(CP(format), channel, nick, status, hops, user, host,
532 name);
533 else
534 put_it(CP(format), channel, nick, status, user, host,
535 name);
536 }
537 }
538 }
539
540 static void
p_privmsg(from,Args)541 p_privmsg(from, Args)
542 u_char *from,
543 **Args;
544 {
545 int level,
546 flag,
547 ch_flag = !IGNORED,
548 list_type,
549 flood_type,
550 log_type;
551 u_char ignore_type;
552 u_char *ptr,
553 *to;
554 u_char *high;
555 int no_flood;
556
557 if (!from)
558 return;
559 PasteArgs(Args, 1);
560 to = Args[0];
561 ptr = Args[1];
562 if (!to || !ptr)
563 return;
564 save_message_from();
565
566 if (is_channel(to))
567 {
568 message_from(to, LOG_MSG);
569 malloc_strcpy(&public_nick, from);
570 if (!is_on_channel(to, parsing_server_index, from))
571 {
572 log_type = LOG_PUBLIC;
573 ignore_type = IGNORE_PUBLIC;
574 list_type = PUBLIC_MSG_LIST;
575 flood_type = PUBLIC_FLOOD;
576 }
577 else
578 {
579 log_type = LOG_PUBLIC;
580 ignore_type = IGNORE_PUBLIC;
581 if (is_current_channel(to, parsing_server_index, 0))
582 list_type = PUBLIC_LIST;
583 else
584 list_type = PUBLIC_OTHER_LIST;
585 flood_type = PUBLIC_FLOOD;
586 }
587 }
588 else
589 {
590 message_from(from, LOG_MSG);
591 flood_type = MSG_FLOOD;
592 if (my_stricmp(to, get_server_nickname(parsing_server_index)))
593 {
594 log_type = LOG_WALL;
595 ignore_type = IGNORE_WALLS;
596 list_type = MSG_GROUP_LIST;
597 }
598 else
599 {
600 log_type = LOG_MSG;
601 ignore_type = IGNORE_MSGS;
602 list_type = MSG_LIST;
603 }
604 }
605 flag = double_ignore(from, FromUserHost, ignore_type);
606 ch_flag = double_ignore(to, UNULL, ignore_type);
607 switch (flag)
608 {
609 case IGNORED:
610 if ((list_type == MSG_LIST) && get_int_var(SEND_IGNORE_MSG_VAR))
611 send_to_server("NOTICE %s :%s is ignoring you", from,
612 get_server_nickname(parsing_server_index));
613 goto out;
614 case HIGHLIGHTED:
615 high = &highlight_char;
616 break;
617 default:
618 high = empty_string;
619 break;
620 }
621
622 if (ch_flag == IGNORED)
623 goto out;
624
625 level = set_lastlog_msg_level(log_type);
626 ptr = do_ctcp(from, to, ptr);
627 if (!ptr || !*ptr)
628 goto out;
629 if ((flag != DONT_IGNORE) && (ignore_usernames & ignore_type) && !FromUserHost)
630 add_to_whois_queue(from, whois_ignore_msgs, "%s", ptr);
631 else
632 {
633 no_flood = check_flooding(from, flood_type, ptr);
634 if (sed == 0 || do_hook(ENCRYPTED_PRIVMSG_LIST,"%s %s %s",from, to, ptr))
635 {
636 switch (list_type)
637 {
638 case PUBLIC_MSG_LIST:
639 if (!checkgrep(to, ptr))
640 goto out;
641 if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr))
642 put_it("%s(%s/%s)%s %s", high, from, to, high, ptr);
643 break;
644 case MSG_GROUP_LIST:
645 if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr))
646 put_it("%s-%s:%s-%s %s", high, from, to, high, ptr);
647 break;
648 case MSG_LIST:
649 if (!no_flood)
650 break;
651
652 malloc_strcpy(&recv_nick, from);
653 if (away_set)
654 beep_em(get_int_var(BEEP_WHEN_AWAY_VAR));
655 if (do_hook(list_type, "%s %s", from, ptr))
656 {
657 if (server_list[parsing_server_index].away_set)
658 {
659 time_t t;
660 u_char *msg = (u_char *) 0;
661
662 t = time((time_t *) 0);
663 msg = (u_char *) new_malloc(my_strlen(ptr) + 20);
664 sprintf(CP(msg), "%s <%.16s>", ptr, ctime(&t));
665 put_it("%s*%s(%s)*%s %s",
666 high, from, FromUserHost, high, msg);
667 new_free(&msg);
668 }
669 else
670 put_it("%s*%s(%s)*%s %s", high, from, FromUserHost, high, ptr);
671 }
672 if (server_list[parsing_server_index].away_set)
673 add_to_awaylog("*%s(%s)* %s", from, FromUserHost, ptr);
674 addredirect(REDIRECT_MSG, "*%s(%s)* %s", from, FromUserHost, ptr);
675 add_tab_key(0, "msg ", from);
676 break;
677 case PUBLIC_LIST:
678 if (get_int_var(MAKE_NOTICE_MSG_VAR))
679 doing_privmsg = 1;
680 if (!checkgrep(to, ptr))
681 goto out;
682 if (no_flood && do_hook(list_type, "%s %s %s", from,
683 to, ptr))
684 put_it("%s<%s>%s %s", high, from, high, ptr);
685 doing_privmsg = 0;
686 break;
687 case PUBLIC_OTHER_LIST:
688 if (get_int_var(MAKE_NOTICE_MSG_VAR))
689 doing_privmsg = 1;
690 if (!checkgrep(to, ptr))
691 goto out;
692 if (no_flood && do_hook(list_type, "%s %s %s", from,
693 to, ptr))
694 put_it("%s<%s:%s>%s %s", high, from, to, high,
695 ptr);
696 doing_privmsg = 0;
697 break;
698 }
699 if (beep_on_level & log_type)
700 beep_em(1);
701 }
702 }
703 set_lastlog_msg_level(level);
704 out:
705 restore_message_from();
706 }
707
708 #if 0
709 static void
710 p_msgcmd(from, ArgList)
711 u_char *from,
712 **ArgList;
713 {
714 u_char *high,
715 *channel,
716 *text;
717 int log_type,
718 no_flooding;
719 int flag;
720
721 if (!from)
722 return;
723 flag = double_ignore(from, FromUserHost, IGNORE_PUBLIC);
724 switch (flag)
725 {
726 case IGNORED:
727 return;
728 case HIGHLIGHTED:
729 high = &highlight_char;
730 break;
731 default:
732 high = empty_string;
733 break;
734 }
735 if ((channel = real_channel()) == (u_char *) 0)
736 return;
737 text = do_ctcp(from, channel, ArgList[0]);
738 if (!text || !*text)
739 return;
740 malloc_strcpy((u_char **) &public_nick, from);
741 log_type = set_lastlog_msg_level(LOG_PUBLIC);
742 no_flooding = check_flooding(from, PUBLIC_FLOOD, text);
743 save_message_from();
744 message_from(channel, LOG_PUBLIC);
745 if (is_current_channel(channel, parsing_server_index, 0))
746 {
747 if (get_int_var(MAKE_NOTICE_MSG_VAR))
748 doing_privmsg = 1;
749 if (no_flooding && do_hook(PUBLIC_LIST, "%s %s %s", from, channel, text))
750 put_it("%s<%s>%s %s", high, from, high, text);
751 doing_privmsg = 0;
752 }
753 else
754 {
755 if (get_int_var(MAKE_NOTICE_MSG_VAR))
756 doing_privmsg = 1;
757 if (no_flooding && do_hook(PUBLIC_OTHER_LIST, "%s %s %s", from,
758 channel, text))
759 put_it("%s<%s:%s>%s %s", high, from, channel, high,
760 text);
761 doing_privmsg = 0;
762 }
763 restore_message_from();
764 if (beep_on_level & LOG_PUBLIC)
765 beep_em(1);
766 set_lastlog_msg_level(log_type);
767 }
768 #endif
769
770 /*ARGSUSED*/
771 static void
p_quit(from,ArgList)772 p_quit(from, ArgList)
773 u_char *from,
774 **ArgList;
775 {
776 int one_prints = 0;
777 u_char *chan;
778 u_char *Reason;
779 int flag, ch_flag;
780
781 if (!from)
782 return;
783 flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
784 save_message_from();
785 if (flag != IGNORED)
786 {
787 PasteArgs(ArgList, 0);
788 Reason = ArgList[0] ? ArgList[0] : q_mark;
789 for (chan = walk_channels(from, 1, parsing_server_index); chan; chan = walk_channels(from, 0, -1))
790 {
791 ch_flag = double_ignore(chan, NULL, IGNORE_CRAP);
792 message_from(chan, LOG_CRAP);
793 if (ch_flag != IGNORED
794 && checkgrep(chan, Reason)
795 && do_hook(CHANNEL_SIGNOFF_LIST, "%s %s %s", chan, from, Reason))
796 one_prints = 1;
797 }
798 if (one_prints)
799 {
800 message_from(what_channel(from, parsing_server_index), LOG_CRAP);
801 if (do_hook(SIGNOFF_LIST, "%s %s", from, Reason))
802 say("SignOff: %s (%s)", from, Reason);
803 }
804 }
805 message_from((u_char *) 0, LOG_CURRENT);
806
807 /* XXX: check for netsplits */
808 remove_from_channel((u_char *) 0, from, parsing_server_index);
809 notify_mark(from, 0, 0, UNULL, UNULL, 0);
810 nchk_orignick(from);
811
812 restore_message_from();
813 }
814
815 /*ARGSUSED*/
816 static void
p_pong(from,ArgList)817 p_pong(from, ArgList)
818 u_char *from,
819 **ArgList;
820 {
821 int flag;
822
823 if (!from)
824 return;
825 flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
826 if (flag == IGNORED)
827 return;
828
829 if (ArgList[0])
830 say("%s: PONG received from %s", ArgList[0], from);
831 }
832
833 /*ARGSUSED*/
834 static void
p_error(from,ArgList)835 p_error(from, ArgList)
836 u_char *from,
837 **ArgList;
838 {
839 PasteArgs(ArgList, 0);
840 if (!ArgList[0])
841 return;
842 say("%s", ArgList[0]);
843 }
844
845 static void
p_channel(from,ArgList)846 p_channel(from, ArgList)
847 u_char *from;
848 u_char **ArgList;
849 {
850 int join;
851 u_char *channel;
852 int flag, ch_flag;
853 u_char *s, *ov = NULL;
854 int chan_oper = 0, chan_voice = 0;
855
856 if (!from)
857 return;
858 flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
859 if (my_strcmp(ArgList[0], zero))
860 {
861 join = 1;
862 channel = ArgList[0];
863 /*
864 * this \007 should be \a but a lot of compilers are
865 * broken. *sigh* -mrg
866 */
867 if ((ov = s = my_index(channel, '\007')))
868 {
869 *s = '\0';
870 ov++;
871 while (*++s)
872 {
873 if (*s == 'o')
874 chan_oper = 1;
875 if (*s == 'v')
876 chan_voice = 1;
877
878 }
879 }
880 malloc_strcpy(&joined_nick, from);
881 }
882 else
883 {
884 channel = zero;
885 join = 0;
886 }
887 /*
888 * this channel cache maintenance is handled in nincache.c
889 *
890 *
891 if (!my_stricmp(from, get_server_nickname(parsing_server_index)))
892 {
893 if (join)
894 {
895 add_channel(channel, parsing_server_index, CHAN_JOINED, (ChannelList *) 0);
896 if (get_server_version(parsing_server_index) == Server2_5)
897 send_to_server("NAMES %s", channel);
898 send_to_server("MODE %s", channel);
899 }
900 else
901 remove_channel(channel, parsing_server_index);
902 }
903 else
904 {
905 if (join)
906 add_to_channel(channel, from, parsing_server_index, chan_oper, chan_voice);
907 else
908 remove_from_channel(channel, from, parsing_server_index);
909 }
910 *
911 */
912 if (join)
913 {
914 if (!get_channel_oper(channel, parsing_server_index))
915 in_on_who = 1;
916 save_message_from();
917 message_from(channel, LOG_CRAP);
918 ch_flag = double_ignore(channel, NULL, IGNORE_CRAP);
919 if (flag != IGNORED
920 && ch_flag != IGNORED)
921 {
922 u_char tbuf[512];
923
924 my_strmcpy(tbuf, from, sizeof(tbuf)-1);
925 my_strmcat(tbuf, " ", sizeof(tbuf)-1);
926 if (FromUserHost)
927 {
928 my_strmcat(tbuf, "(", sizeof(tbuf)-1);
929 my_strmcat(tbuf, FromUserHost, sizeof(tbuf)-1);
930 my_strmcat(tbuf, ") ", sizeof(tbuf)-1);
931 }
932 my_strmcat(tbuf, "has joined channel ", sizeof(tbuf)-1);
933 my_strmcat(tbuf, channel, sizeof(tbuf)-1);
934 if (ov && *ov)
935 {
936 my_strmcat(tbuf, " +", sizeof(tbuf)-1);
937 my_strmcat(tbuf, ov, sizeof(tbuf)-1);
938 }
939 if (checkgrep(channel, tbuf)
940 && do_hook(JOIN_LIST, "%s %s %s", from,
941 channel, ov ? ov : empty_string))
942 put_info("%s", tbuf);
943 }
944 restore_message_from();
945 in_on_who = 0;
946 }
947 else
948 say("someone left!");
949 }
950
951 static void
p_invite(from,ArgList)952 p_invite(from, ArgList)
953 u_char *from,
954 **ArgList;
955 {
956 u_char *high;
957 int flag, ch_flag;
958
959 if (!from)
960 return;
961 flag = double_ignore(from, FromUserHost, IGNORE_INVITES);
962 switch (flag)
963 {
964 case IGNORED:
965 if (get_int_var(SEND_IGNORE_MSG_VAR))
966 send_to_server("NOTICE %s :%s is ignoring you",
967 from, get_server_nickname(parsing_server_index));
968 return;
969 case HIGHLIGHTED:
970 high = &highlight_char;
971 break;
972 default:
973 high = empty_string;
974 break;
975 }
976 if (ArgList[0] && ArgList[1])
977 {
978 ch_flag = double_ignore(ArgList[1], NULL, IGNORE_INVITES);
979 if ((flag != DONT_IGNORE)
980 && ch_flag != DONT_IGNORE
981 && (ignore_usernames & IGNORE_INVITES)
982 && !FromUserHost)
983 add_to_whois_queue(from, whois_ignore_invites, "%s", ArgList[1]);
984 else
985 {
986 save_message_from();
987 message_from(from, LOG_CRAP);
988 if (do_hook(INVITE_LIST, "%s %s", from, ArgList[1]))
989 say("%s%s(%s)%s invites you to channel %s", high,
990 from, FromUserHost, high, ArgList[1]);
991 if (server_list[parsing_server_index].away_set)
992 add_to_awaylog("%s(%s) invites you to channel %s",
993 from, FromUserHost, ArgList[1]);
994 restore_message_from();
995 malloc_strcpy(&invite_channel, ArgList[1]);
996 malloc_strcpy(&recv_nick, from);
997 }
998 }
999 }
1000
1001 static void
p_server_kill(from,ArgList)1002 p_server_kill(from, ArgList)
1003 u_char *from,
1004 **ArgList;
1005 {
1006 /*
1007 * this is so bogus checking for a server name having a '.'
1008 * in it - phone, april 1993.
1009 */
1010 if (my_index(from, '.'))
1011 say("You have been rejected by server %s %s", from,
1012 ArgList[1] ? ArgList[1] : UP("(No Reason Given)"));
1013 else
1014 {
1015 say("You have been killed by operator %s %s", from,
1016 ArgList[1] ? ArgList[1] : (u_char *) "(No Reason Given)");
1017
1018 /* if we were away and missed this output, put it in the log */
1019 if (server_list[parsing_server_index].away_set)
1020 add_to_awaylog("You were killed by operator %s %s", from,
1021 ArgList[1] ? ArgList[1] : (u_char *) "(No Reason Given)");
1022
1023 #ifdef FASCIST_QUIT_ON_OPERATOR_KILL
1024 irc_exit();
1025 #endif /* FASCIST_QUIT_ON_OPERATOR_KILL */
1026 }
1027 close_server(parsing_server_index, empty_string);
1028 window_check_servers();
1029 if (!connected_to_server)
1030 say("Use /SERVER to reconnect to a server");
1031 }
1032
1033 /*
1034 * this has been moved to nincache..
1035 *
1036 static void
1037 p_ping(ArgList)
1038 u_char **ArgList;
1039 {
1040 PasteArgs(ArgList, 0);
1041 send_to_server("PONG :%s", ArgList[0]);
1042 }
1043 */
1044
1045 static void
p_nick(from,ArgList,its_me,fnick)1046 p_nick(from, ArgList, its_me, fnick)
1047 u_char *from,
1048 **ArgList, *fnick;
1049 {
1050 int one_prints = 0;
1051 u_char *chan;
1052 u_char *line;
1053 int flag, ch_flag;
1054
1055 if (!from)
1056 return;
1057 flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
1058 line = ArgList[0];
1059 /*
1060 * moved some of this to nincache.c
1061 *
1062 * its_me is now passed in from parse_server()
1063 *
1064 if (my_stricmp(from, get_server_nickname(parsing_server_index)) == 0){
1065 if (parsing_server_index == primary_server)
1066 malloc_strcpy(&nickname, line);
1067 set_server_nickname(parsing_server_index, line);
1068 its_me = 1;
1069 }
1070 *
1071 *
1072 *
1073 * this is just a bit hackish, if it_me, then we were the person changing their nick...
1074 *
1075 * that means we now have to look for channels with my new nickname and report that
1076 * the nick change occurred! (from -> current nick)
1077 *
1078 */
1079
1080 save_message_from();
1081 if (flag != IGNORED)
1082 {
1083 for (chan = walk_channels(fnick, 1, parsing_server_index); chan;
1084 chan = walk_channels(fnick, 0, -1))
1085 {
1086 ch_flag = double_ignore(chan, UNULL, IGNORE_CRAP);
1087 message_from(chan, LOG_CRAP);
1088 if (ch_flag != IGNORED
1089 && checkgrep(chan, UNULL)
1090 && do_hook(CHANNEL_NICK_LIST, "%s %s %s", chan, from, line))
1091 one_prints = 1;
1092 }
1093 if (one_prints)
1094 {
1095 if (its_me)
1096 message_from((u_char *) 0, LOG_CRAP);
1097 else
1098 message_from(what_channel(fnick, parsing_server_index), LOG_CRAP);
1099 if (do_hook(NICKNAME_LIST, "%s %s", from, line))
1100 say("%s is now known as %s", from, line);
1101 }
1102 }
1103 /*
1104 * more stuff that's moved to nincache.c
1105 *
1106 rename_nick(from, line, parsing_server_index);
1107 if (my_stricmp(from, line))
1108 {
1109 message_from((u_char *) 0, LOG_CURRENT);
1110 notify_mark(from, 0, 0);
1111 notify_mark(line, 1, 0);
1112 }
1113 */
1114 restore_message_from();
1115 }
1116
1117 static void
p_mode(from,ArgList)1118 p_mode(from, ArgList)
1119 u_char *from,
1120 **ArgList;
1121 {
1122 u_char *channel;
1123 u_char *line;
1124 int flag, ch_flag;
1125
1126 if (!from)
1127 return;
1128 flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
1129 PasteArgs(ArgList, 1);
1130 channel = ArgList[0];
1131 line = ArgList[1];
1132 save_message_from();
1133 message_from(channel, LOG_CRAP);
1134 if (channel && line)
1135 {
1136 if (is_channel(channel))
1137 {
1138 ch_flag = double_ignore(channel, UNULL, IGNORE_CRAP);
1139 if (flag != IGNORED
1140 && ch_flag != IGNORED
1141 && checkgrep(channel, UNULL)
1142 && do_hook(MODE_LIST, "%s %s %s",
1143 from, channel, line))
1144 say("Mode change \"%s\" on channel %s by %s",
1145 line, channel, from);
1146 /*
1147 * moved to nincache.c
1148 *
1149 update_channel_mode(channel, parsing_server_index, line);
1150 */
1151 }
1152 else
1153 {
1154 if (flag != IGNORED && do_hook(MODE_LIST, "%s %s %s",
1155 from, channel, line))
1156 say("Mode change \"%s\" for user %s by %s",
1157 line, channel, from);
1158 /*
1159 * moved to nincache.c
1160 *
1161 update_user_mode(line);
1162 */
1163 }
1164 update_all_status();
1165 }
1166 restore_message_from();
1167 }
1168
1169 static void
p_kick(from,ArgList)1170 p_kick(from, ArgList)
1171 u_char *from,
1172 **ArgList;
1173 {
1174 u_char *channel,
1175 *who,
1176 *comment;
1177 int flag, ch_flag, w_flag;
1178
1179 if (!from)
1180 return;
1181 channel = ArgList[0];
1182 who = ArgList[1];
1183 comment = ArgList[2];
1184
1185 if (channel && who)
1186 {
1187 flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
1188 w_flag = double_ignore(who, UNULL, IGNORE_CRAP);
1189 ch_flag = double_ignore(channel, UNULL, IGNORE_CRAP);
1190
1191 save_message_from();
1192 message_from(channel, LOG_CRAP);
1193 if (my_stricmp(who, get_server_nickname(parsing_server_index)) == 0)
1194 {
1195 if (comment && *comment)
1196 {
1197 if (do_hook(KICK_LIST, "%s %s %s %s", who,
1198 from, channel, comment))
1199 say("You have been kicked off channel %s by %s (%s)",
1200 channel, from, comment);
1201 if (server_list[parsing_server_index].away_set)
1202 add_to_awaylog("You have been kicked off channel %s by %s (%s)",
1203 channel, from, comment);
1204 }
1205 else
1206 {
1207 if (do_hook(KICK_LIST, "%s %s %s", who, from,
1208 channel))
1209 say("You have been kicked off channel %s by %s",
1210 channel, from);
1211 if (server_list[parsing_server_index].away_set)
1212 add_to_awaylog("You have been kicked off channel %s by %s",
1213 channel, from);
1214 }
1215 /*
1216 * handled in nincache.c
1217 *
1218 remove_channel(channel, parsing_server_index);
1219 update_all_status();
1220 */
1221 }
1222 else
1223 {
1224 if (flag != IGNORED
1225 && w_flag != IGNORED
1226 && ch_flag != IGNORED)
1227 {
1228 if (comment && *comment)
1229 {
1230 if (checkgrep(channel, comment)
1231 && do_hook(KICK_LIST, "%s %s %s %s", who,
1232 from, channel, comment))
1233 say("%s has been kicked off channel %s by %s (%s)",
1234 who, channel, from, comment);
1235 }
1236 else
1237 {
1238 if (checkgrep(channel, UNULL)
1239 && do_hook(KICK_LIST, "%s %s %s", who, from,
1240 channel))
1241 say("%s has been kicked off channel %s by %s",
1242 who, channel, from);
1243 }
1244 /*
1245 * handled in nincache.c
1246 *
1247 remove_from_channel(channel, who, parsing_server_index);
1248 */
1249 }
1250 }
1251 restore_message_from();
1252 }
1253 }
1254
1255 static void
p_part(from,ArgList)1256 p_part(from, ArgList)
1257 u_char *from,
1258 **ArgList;
1259 {
1260 u_char *channel;
1261 u_char *comment;
1262 int flag, ch_flag;
1263
1264 if (!from)
1265 return;
1266 flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
1267 channel = ArgList[0];
1268 /*
1269 * argh.. we don't care if we're on the channel or not.. just go on
1270 *
1271 if (!is_on_channel(channel, parsing_server_index, from))
1272 return;
1273 */
1274 ch_flag = double_ignore(channel, UNULL, IGNORE_CRAP);
1275 comment = ArgList[1];
1276 if (!comment)
1277 comment = empty_string;
1278 in_on_who = 1;
1279 if (flag != IGNORED
1280 && ch_flag != IGNORED)
1281 {
1282 save_message_from();
1283 message_from(channel, LOG_CRAP);
1284 if (checkgrep(channel, UNULL)
1285 && do_hook(LEAVE_LIST, "%s %s %s", from, channel, comment))
1286 {
1287 if (comment && *comment != '\0')
1288 say("%s has left %s (%s)", from, channel, comment);
1289 else
1290 say("%s has left %s", from, channel);
1291 }
1292 restore_message_from();
1293 }
1294 /*
1295 * handled in nincache.c
1296 *
1297 if (my_stricmp(from, get_server_nickname(parsing_server_index)) == 0)
1298 remove_channel(channel, parsing_server_index);
1299 else
1300 remove_from_channel(channel, from, parsing_server_index);
1301 */
1302 in_on_who = 0;
1303 }
1304
1305
1306 /*
1307 * parse_server: parses messages from the server, doing what should be done
1308 * with them
1309 */
1310 void
parse_server(line)1311 parse_server(line)
1312 u_char *line;
1313 {
1314 server_list[parsing_server_index].parse_server(line);
1315 }
1316
1317 void
irc2_parse_server(line)1318 irc2_parse_server(line)
1319 u_char *line;
1320 {
1321 u_char *from,
1322 *comm,
1323 *end,
1324 *copy = (u_char *) 0;
1325 int numeric, flag = 0;
1326 u_char **ArgList;
1327 u_char *TrueArgs[MAXPARA + 1];
1328 u_char *str_flag = UNULL;
1329
1330 if ((u_char *) 0 == line)
1331 return;
1332
1333 end = my_strlen(line) + line;
1334 if (*--end == '\n')
1335 *end-- = '\0';
1336 if (*end == '\r')
1337 *end-- = '\0';
1338
1339 /* do the cache stuff in nincache.c */
1340 if (!parse_into_cache(line, &flag, &str_flag))
1341 return;
1342
1343 if (*line == ':')
1344 {
1345 if (!do_hook(RAW_IRC_LIST, "%s", line + 1))
1346 return;
1347 }
1348 else if (!do_hook(RAW_IRC_LIST, "%s %s", "*", line))
1349 return;
1350
1351 malloc_strcpy(©, line);
1352 ArgList = TrueArgs;
1353 BreakArgs(copy, &from, ArgList);
1354
1355 if (!(comm = (*ArgList++)))
1356 return; /* Empty line from server - ByeBye */
1357
1358 /*
1359 * XXX!!!
1360 * this should fail on '1xxx'!!!
1361 */
1362 if (0 != (numeric = my_atoi(comm)))
1363 numbered_command(from, numeric, ArgList);
1364 else if (my_strcmp(comm, "NAMREPLY") == 0)
1365 funny_namreply(from, ArgList);
1366 else if (my_strcmp(comm, "WHOREPLY") == 0)
1367 whoreply(from, ArgList);
1368 else if (my_strcmp(comm, "NOTICE") == 0)
1369 parse_notice(from, ArgList);
1370 /* everything else is handled locally */
1371 else if (my_strcmp(comm, "PRIVMSG") == 0)
1372 p_privmsg(from, ArgList);
1373 else if (my_strcmp(comm, "JOIN") == 0)
1374 p_channel(from, ArgList);
1375 else if (my_strcmp(comm, "PART") == 0)
1376 p_part(from, ArgList);
1377 else if (my_strcmp(comm, "CHANNEL") == 0)
1378 p_channel(from, ArgList);
1379 else if (my_strcmp(comm, "MSG") == 0)
1380 /*p_msgcmd(from, ArgList)*/;
1381 else if (my_strcmp(comm, "QUIT") == 0)
1382 p_quit(from, ArgList);
1383 else if (my_strcmp(comm, "WALL") == 0)
1384 p_wall(from, ArgList);
1385 else if (my_strcmp(comm, "WALLOPS") == 0)
1386 p_wallops(from, ArgList);
1387 else if (my_strcmp(comm, "LINREPLY") == 0)
1388 p_linreply(ArgList);
1389 /* else if (my_strcmp(comm, "PING") == 0)
1390 p_ping(ArgList);
1391 */
1392 else if (my_strcmp(comm, "TOPIC") == 0)
1393 p_topic(from, ArgList);
1394 else if (my_strcmp(comm, "PONG") == 0)
1395 p_pong(from, ArgList);
1396 else if (my_strcmp(comm, "INVITE") == 0)
1397 p_invite(from, ArgList);
1398 else if (my_strcmp(comm, "NICK") == 0)
1399 p_nick(from, ArgList, flag, str_flag);
1400 else if (my_strcmp(comm, "KILL") == 0)
1401 p_server_kill(from, ArgList);
1402 else if (my_strcmp(comm, "MODE") == 0)
1403 p_mode(from, ArgList);
1404 else if (my_strcmp(comm, "KICK") == 0)
1405 p_kick(from, ArgList);
1406 else if (my_strcmp(comm, "ERROR") == 0)
1407 p_error(from, ArgList);
1408 else if (my_strcmp(comm, "ERROR:") == 0) /* Server bug makes this a must */
1409 p_error(from, ArgList);
1410 else
1411 {
1412 PasteArgs(ArgList, 0);
1413 if (from)
1414 put_error("Odd server stuff: \"%s %s\" (%s)", comm,
1415 ArgList[0], from);
1416 else
1417 put_error("Odd server stuff: \"%s %s\"", comm, ArgList[0]);
1418 }
1419 dma_Free(&str_flag);
1420 new_free(©);
1421 }
1422