/* * parse.c: handles messages from the server. Believe it or not. I * certainly wouldn't if I were you. * * Written By Michael Sandrof * * Copyright (c) 1990 Michael Sandrof. * Copyright (c) 1991, 1992 Troy Rollo. * Copyright (c) 1992-2000 Matthew R. Green. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "irc.h" IRCII_RCSID("@(#)$Id: parse.c,v 1.76 2000/04/04 03:10:57 mrg Exp $"); #include "server.h" #include "names.h" #include "vars.h" #include "ctcp.h" #include "hook.h" #include "edit.h" #include "ignore.h" #include "whois.h" #include "lastlog.h" #include "ircaux.h" #include "funny.h" #include "crypt.h" #include "ircterm.h" #include "flood.h" #include "window.h" #include "screen.h" #include "output.h" #include "numbers.h" #include "parse.h" #include "notify.h" #define STRING_CHANNEL '+' #define MULTI_CHANNEL '#' #define LOCAL_CHANNEL '&' #define SAFE_CHANNEL '!' #define MAXPARA 15 /* Taken from the ircd */ static void BreakArgs _((u_char *, u_char **, u_char **)); static void p_linreply _((u_char **)); static void p_ping _((u_char **)); static void p_topic _((u_char *, u_char **)); static void p_wall _((u_char *, u_char **)); static void p_wallops _((u_char *, u_char **)); static void p_privmsg _((u_char *, u_char **)); /*static void p_msgcmd _((u_char *, u_char **));*/ static void p_quit _((u_char *, u_char **)); static void p_pong _((u_char *, u_char **)); static void p_error _((u_char *, u_char **)); static void p_channel _((u_char *, u_char **)); static void p_invite _((u_char *, u_char **)); static void p_server_kill _((u_char *, u_char **)); static void p_nick _((u_char *, u_char **)); static void p_mode _((u_char *, u_char **)); static void p_kick _((u_char *, u_char **)); static void p_part _((u_char *, u_char **)); /* * joined_nick: the nickname of the last person who joined the current * channel */ u_char *joined_nick = (u_char *) 0; /* public_nick: nick of the last person to send a message to your channel */ u_char *public_nick = (u_char *) 0; /* User and host information from server 2.7 */ u_char *FromUserHost = (u_char *) 0; /* doing a PRIVMSG */ int doing_privmsg = 0; /* * is_channel: determines if the argument is a channel. If it's a number, * begins with MULTI_CHANNEL and has no '*', or STRING_CHANNEL, then its a * channel. */ int is_channel(to) u_char *to; { int version; if (to == 0) return (0); version = get_server_version(from_server); return ((version < Server2_7 && (isdigit(*to) || (*to == STRING_CHANNEL) || *to == '-')) || (version > Server2_5 && *to == MULTI_CHANNEL) || (version > Server2_7 && *to == LOCAL_CHANNEL) || (version > Server2_8 && *to == STRING_CHANNEL) || (version > Server2_9 && *to == SAFE_CHANNEL) || (version == ServerICB && my_stricmp(to, get_server_icbgroup(from_server)) == 0)); } u_char * PasteArgs(Args, StartPoint) u_char **Args; int StartPoint; { int i; for (; StartPoint; Args++, StartPoint--) if (!*Args) return (u_char *) 0; for (i = 0; Args[i] && Args[i+1]; i++) Args[i][my_strlen(Args[i])] = ' '; Args[1] = (u_char *) 0; return Args[0]; } /* * BreakArgs: breaks up the line from the server, in to where its from, * setting FromUserHost if it should be, and returns all the arguements * that are there. Re-written by phone, dec 1992. */ static void BreakArgs(Input, Sender, OutPut) u_char *Input; u_char **Sender; u_char **OutPut; { u_char *s = Input, *t; int ArgCount = 0; /* * Get sender from :sender and user@host if :nick!user@host */ FromUserHost = (u_char *) 0; if (*Input == ':') { u_char *tmp; *Input++ = '\0'; if ((s = (u_char *) my_index(Input, ' ')) != (u_char *) 0) *s++ = '\0'; *Sender = Input; if ((tmp = (u_char *) my_index(*Sender, '!')) != (u_char *) 0) { *tmp++ = '\0'; FromUserHost = tmp; } } else *Sender = empty_string; if (!s) return; for (;;) { while (*s == ' ') *s++ = '\0'; if (!*s) break; if (*s == ':') { for (t = s; *t; t++) *t = *(t + 1); OutPut[ArgCount++] = s; break; } OutPut[ArgCount++] = s; if (ArgCount >= MAXPARA) break; for (; *s != ' ' && *s; s++) ; } OutPut[ArgCount] = (u_char *) 0; } /* beep_em: Not hard to figure this one out */ void beep_em(beeps) int beeps; { int cnt, i; for (cnt = beeps, i = 0; i < cnt; i++) term_beep(); } /* in response to a TOPIC message from the server */ static void p_topic(from, ArgList) u_char *from, **ArgList; { int flag; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_CRAP); if (flag == IGNORED) return; save_message_from(); if (!ArgList[1]) { message_from((u_char *) 0, LOG_CRAP); if (do_hook(TOPIC_LIST, "%s * %s", from, ArgList[0])) say("%s has changed the topic to %s", from, ArgList[0]); } else { message_from(ArgList[0], LOG_CRAP); if (do_hook(TOPIC_LIST, "%s %s %s", from, ArgList[0], ArgList[1])) say("%s has changed the topic on channel %s to %s", from, ArgList[0], ArgList[1]); } restore_message_from(); } static void p_linreply(ArgList) u_char **ArgList; { PasteArgs(ArgList, 0); say("%s", ArgList[0]); } static void p_wall(from, ArgList) u_char *from, **ArgList; { int flag, level; u_char *line; u_char *high; if (!from) return; PasteArgs(ArgList, 0); if (!(line = ArgList[0])) return; flag = double_ignore(from, FromUserHost, IGNORE_WALLS); save_message_from(); message_from(from, LOG_WALL); if (flag != IGNORED) { if (flag == HIGHLIGHTED) high = &highlight_char; else high = empty_string; if ((flag != DONT_IGNORE) && (ignore_usernames & IGNORE_WALLS) && !FromUserHost) add_to_whois_queue(from, whois_ignore_walls, "%s",line); else { level = set_lastlog_msg_level(LOG_WALL); if (check_flooding(from, WALL_FLOOD, line) && do_hook(WALL_LIST, "%s %s", from, line)) put_it("%s#%s#%s %s", high, from, high, line); if (beep_on_level & LOG_WALL) beep_em(1); set_lastlog_msg_level(level); } } restore_message_from(); } static void p_wallops(from, ArgList) u_char *from, **ArgList; { int flag, level; u_char *line; if (!from) return; if (!(line = PasteArgs(ArgList, 0))) return; flag = double_ignore(from, FromUserHost, IGNORE_WALLOPS); level = set_lastlog_msg_level(LOG_WALLOP); save_message_from(); message_from(from, LOG_WALLOP); if (my_index(from, '.')) { u_char *high; if (flag != IGNORED) { if (flag == HIGHLIGHTED) high = &highlight_char; else high = empty_string; if (do_hook(WALLOP_LIST, "%s S %s", from, line)) put_it("%s!%s!%s %s", high, from, high, line); if (beep_on_level & LOG_WALLOP) beep_em(1); } } else { if (get_int_var(USER_WALLOPS_VAR)) { if ((flag != DONT_IGNORE) && (check_flooding(from, WALLOP_FLOOD, line))) add_to_whois_queue(from, whois_new_wallops, "%s", line); } else if (my_strcmp(from, get_server_nickname(get_window_server(0))) != 0) put_it("!%s! %s", from, line); } set_lastlog_msg_level(level); restore_message_from(); } /*ARGSUSED*/ void whoreply(from, ArgList) u_char **ArgList, *from; { static u_char format[40]; static int last_width = -1; int ok = 1; u_char *channel, *user, *host, *server, *nick, *status, *name; int i; FILE *fip; u_char buf_data[BUFSIZ]; if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR)) { if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0) sprintf(CP(format), "%%-%u.%us %%-9s %%-3s %%s@%%s (%%s)", (u_char) last_width, (u_char) last_width); else my_strcpy(format, "%s\t%-9s %-3s %s@%s (%s)"); } i = 0; channel = user = host = server = nick = status = name = empty_string; if (ArgList[i]) channel = ArgList[i++]; if (ArgList[i]) user = ArgList[i++]; if (ArgList[i]) host = ArgList[i++]; if (ArgList[i]) server = ArgList[i++]; if (ArgList[i]) nick = ArgList[i++]; if (ArgList[i]) status = ArgList[i++]; PasteArgs(ArgList, i); if (*status == 'S') /* this only true for the header WHOREPLY */ { channel = UP("Channel"); if (((who_mask & WHO_FILE) == 0) || (fopen (CP(who_file), "r"))) { if (do_hook(WHO_LIST, "%s %s %s %s %s %s", channel, nick, status, user, host, ArgList[6])) put_it(CP(format), channel, nick, status, user, host, ArgList[6]); return; } } if (ArgList[i]) name = ArgList[i]; if (who_mask) { if (who_mask & WHO_HERE) ok = ok && (*status == 'H'); if (who_mask & WHO_AWAY) ok = ok && (*status == 'G'); if (who_mask & WHO_OPS) ok = ok && (*(status + 1) == '*'); if (who_mask & WHO_LUSERS) ok = ok && (*(status + 1) != '*'); if (who_mask & WHO_CHOPS) ok = ok && ((*(status + 1) == '@') || (*(status + 2) == '@')); if (who_mask & WHO_NAME) ok = ok && wild_match(who_name, user); if (who_mask & WHO_NICK) ok = ok && wild_match(who_nick, nick); if (who_mask & WHO_HOST) ok = ok && wild_match(who_host, host); if (who_mask & WHO_REAL) ok = ok && wild_match(who_real, name); if (who_mask & WHO_SERVER) ok = ok && wild_match(who_server, server); if (who_mask & WHO_FILE) { ok = 0; cannot_open = (u_char *) 0; if ((fip = fopen(CP(who_file), "r")) != (FILE *) 0) { while (fgets ((char *)buf_data, BUFSIZ, fip) != (char *) 0) { buf_data[my_strlen(buf_data)-1] = '\0'; ok = ok || wild_match(buf_data, nick); } fclose (fip); } else cannot_open = who_file; } } if (ok) { if (do_hook(WHO_LIST, "%s %s %s %s %s %s", channel, nick, status, user, host, name)) { if (get_int_var(SHOW_WHO_HOPCOUNT_VAR)) put_it(CP(format), channel, nick, status, user, host, name); else { u_char *tmp; if ((tmp = (u_char *) my_index(name, ' ')) != (u_char *) 0) tmp++; else tmp = name; put_it(CP(format), channel, nick, status, user, host, tmp); } } } } static void p_privmsg(from, Args) u_char *from, **Args; { int level, flag, list_type, flood_type, log_type; u_char ignore_type; u_char *ptr, *to; u_char *high; int no_flood; if (!from) return; PasteArgs(Args, 1); to = Args[0]; ptr = Args[1]; if (!to || !ptr) return; save_message_from(); if (is_channel(to)) { message_from(to, LOG_MSG); malloc_strcpy(&public_nick, from); if (!is_on_channel(to, parsing_server_index, from)) { log_type = LOG_PUBLIC; ignore_type = IGNORE_PUBLIC; list_type = PUBLIC_MSG_LIST; flood_type = PUBLIC_FLOOD; } else { log_type = LOG_PUBLIC; ignore_type = IGNORE_PUBLIC; if (is_current_channel(to, parsing_server_index, 0)) list_type = PUBLIC_LIST; else list_type = PUBLIC_OTHER_LIST; flood_type = PUBLIC_FLOOD; } } else { message_from(from, LOG_MSG); flood_type = MSG_FLOOD; if (my_stricmp(to, get_server_nickname(parsing_server_index))) { log_type = LOG_WALL; ignore_type = IGNORE_WALLS; list_type = MSG_GROUP_LIST; } else { log_type = LOG_MSG; ignore_type = IGNORE_MSGS; list_type = MSG_LIST; } } flag = double_ignore(from, FromUserHost, ignore_type); switch (flag) { case IGNORED: if ((list_type == MSG_LIST) && get_int_var(SEND_IGNORE_MSG_VAR)) send_to_server("NOTICE %s :%s is ignoring you", from, get_server_nickname(parsing_server_index)); goto out; case HIGHLIGHTED: high = &highlight_char; break; default: high = empty_string; break; } level = set_lastlog_msg_level(log_type); ptr = do_ctcp(from, to, ptr); if (!ptr || !*ptr) goto out; if ((flag != DONT_IGNORE) && (ignore_usernames & ignore_type) && !FromUserHost) add_to_whois_queue(from, whois_ignore_msgs, "%s", ptr); else { no_flood = check_flooding(from, flood_type, ptr); if (sed == 0 || do_hook(ENCRYPTED_PRIVMSG_LIST,"%s %s %s",from, to, ptr)) { switch (list_type) { case PUBLIC_MSG_LIST: if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr)) put_it("%s(%s/%s)%s %s", high, from, to, high, ptr); break; case MSG_GROUP_LIST: if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr)) put_it("%s-%s:%s-%s %s", high, from, to, high, ptr); break; case MSG_LIST: if (!no_flood) break; malloc_strcpy(&recv_nick, from); if (away_set) beep_em(get_int_var(BEEP_WHEN_AWAY_VAR)); if (do_hook(list_type, "%s %s", from, ptr)) { if (away_set) { time_t t; u_char *msg = (u_char *) 0; t = time((time_t *) 0); msg = (u_char *) new_malloc(my_strlen(ptr) + 20); sprintf(CP(msg), "%s <%.16s>", ptr, ctime(&t)); put_it("%s*%s*%s %s", high, from, high, msg); new_free(&msg); } else put_it("%s*%s*%s %s", high, from, high, ptr); } break; case PUBLIC_LIST: if (get_int_var(MAKE_NOTICE_MSG_VAR)) doing_privmsg = 1; if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr)) put_it("%s<%s>%s %s", high, from, high, ptr); doing_privmsg = 0; break; case PUBLIC_OTHER_LIST: if (get_int_var(MAKE_NOTICE_MSG_VAR)) doing_privmsg = 1; if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr)) put_it("%s<%s:%s>%s %s", high, from, to, high, ptr); doing_privmsg = 0; break; } if (beep_on_level & log_type) beep_em(1); } } set_lastlog_msg_level(level); out: restore_message_from(); } #if 0 static void p_msgcmd(from, ArgList) u_char *from, **ArgList; { u_char *high, *channel, *text; int log_type, no_flooding; int flag; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_PUBLIC); switch (flag) { case IGNORED: return; case HIGHLIGHTED: high = &highlight_char; break; default: high = empty_string; break; } if ((channel = real_channel()) == (u_char *) 0) return; text = do_ctcp(from, channel, ArgList[0]); if (!text || !*text) return; malloc_strcpy((u_char **) &public_nick, from); log_type = set_lastlog_msg_level(LOG_PUBLIC); no_flooding = check_flooding(from, PUBLIC_FLOOD, text); save_message_from(); message_from(channel, LOG_PUBLIC); if (is_current_channel(channel, parsing_server_index, 0)) { if (get_int_var(MAKE_NOTICE_MSG_VAR)) doing_privmsg = 1; if (no_flooding && do_hook(PUBLIC_LIST, "%s %s %s", from, channel, text)) put_it("%s<%s>%s %s", high, from, high, text); doing_privmsg = 0; } else { if (get_int_var(MAKE_NOTICE_MSG_VAR)) doing_privmsg = 1; if (no_flooding && do_hook(PUBLIC_OTHER_LIST, "%s %s %s", from, channel, text)) put_it("%s<%s:%s>%s %s", high, from, channel, high, text); doing_privmsg = 0; } restore_message_from(); if (beep_on_level & LOG_PUBLIC) beep_em(1); set_lastlog_msg_level(log_type); } #endif /*ARGSUSED*/ static void p_quit(from, ArgList) u_char *from, **ArgList; { int one_prints = 0; u_char *chan; u_char *Reason; int flag; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_CRAP); save_message_from(); if (flag != IGNORED) { PasteArgs(ArgList, 0); Reason = ArgList[0] ? ArgList[0] : (u_char *) "?"; for (chan = walk_channels(from, 1, parsing_server_index); chan; chan = walk_channels(from, 0, -1)) { message_from(chan, LOG_CRAP); if (do_hook(CHANNEL_SIGNOFF_LIST, "%s %s %s", chan, from, Reason)) one_prints = 1; } if (one_prints) { message_from(what_channel(from, parsing_server_index), LOG_CRAP); if (do_hook(SIGNOFF_LIST, "%s %s", from, Reason)) say("Signoff: %s (%s)", from, Reason); } } message_from((u_char *) 0, LOG_CURRENT); remove_from_channel((u_char *) 0, from, parsing_server_index); notify_mark(from, 0, 0); restore_message_from(); } /*ARGSUSED*/ static void p_pong(from, ArgList) u_char *from, **ArgList; { int flag; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_CRAP); if (flag == IGNORED) return; if (ArgList[0]) say("%s: PONG received from %s", ArgList[0], from); } /*ARGSUSED*/ static void p_error(from, ArgList) u_char *from, **ArgList; { PasteArgs(ArgList, 0); if (!ArgList[0]) return; say("%s", ArgList[0]); } static void p_channel(from, ArgList) u_char *from; u_char **ArgList; { int join; u_char *channel; int flag; u_char *s, *ov = NULL; int chan_oper = 0, chan_voice = 0; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_CRAP); if (my_strcmp(ArgList[0], zero)) { join = 1; channel = ArgList[0]; /* * this \007 should be \a but a lot of compilers are * broken. *sigh* -mrg */ if ((ov = s = my_index(channel, '\007'))) { *s = '\0'; ov++; while (*++s) { if (*s == 'o') chan_oper = 1; if (*s == 'v') chan_voice = 1; } } malloc_strcpy(&joined_nick, from); } else { channel = zero; join = 0; } if (!my_stricmp(from, get_server_nickname(parsing_server_index))) { if (join) { add_channel(channel, parsing_server_index, CHAN_JOINED, (ChannelList *) 0); if (get_server_version(parsing_server_index) == Server2_5) send_to_server("NAMES %s", channel); send_to_server("MODE %s", channel); } else remove_channel(channel, parsing_server_index); } else { if (join) add_to_channel(channel, from, parsing_server_index, chan_oper, chan_voice); else remove_from_channel(channel, from, parsing_server_index); } if (join) { if (!get_channel_oper(channel, parsing_server_index)) in_on_who = 1; save_message_from(); message_from(channel, LOG_CRAP); if (flag != IGNORED && do_hook(JOIN_LIST, "%s %s %s", from, channel, ov ? ov : (u_char *) "")) { if (FromUserHost) if (ov && *ov) say("%s (%s) has joined channel %s +%s", from, FromUserHost, channel, ov); else say("%s (%s) has joined channel %s", from, FromUserHost, channel); else if (ov && *ov) say("%s has joined channel %s +%s", from, channel, ov); else say("%s has joined channel %s", from, channel); } restore_message_from(); in_on_who = 0; } } static void p_invite(from, ArgList) u_char *from, **ArgList; { u_char *high; int flag; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_INVITES); switch (flag) { case IGNORED: if (get_int_var(SEND_IGNORE_MSG_VAR)) send_to_server("NOTICE %s :%s is ignoring you", from, get_server_nickname(parsing_server_index)); return; case HIGHLIGHTED: high = &highlight_char; break; default: high = empty_string; break; } if (ArgList[0] && ArgList[1]) { if ((flag != DONT_IGNORE) && (ignore_usernames & IGNORE_INVITES) && !FromUserHost) add_to_whois_queue(from, whois_ignore_invites, "%s", ArgList[1]); else { save_message_from(); message_from(from, LOG_CRAP); if (do_hook(INVITE_LIST, "%s %s", from, ArgList[1])) say("%s%s%s invites you to channel %s", high, from, high, ArgList[1]); restore_message_from(); malloc_strcpy(&invite_channel, ArgList[1]); malloc_strcpy(&recv_nick, from); } } } static void p_server_kill(from, ArgList) u_char *from, **ArgList; { /* * this is so bogus checking for a server name having a '.' * in it - phone, april 1993. */ if (my_index(from, '.')) say("You have been rejected by server %s", from); else { say("You have been killed by operator %s %s", from, ArgList[1] ? ArgList[1] : (u_char *) "(No Reason Given)"); #ifdef FASCIST_QUIT_ON_OPERATOR_KILL irc_exit(); #endif /* FASCIST_QUIT_ON_OPERATOR_KILL */ } close_server(parsing_server_index, empty_string); window_check_servers(); if (!connected_to_server) say("Use /SERVER to reconnect to a server"); } static void p_ping(ArgList) u_char **ArgList; { PasteArgs(ArgList, 0); send_to_server("PONG :%s", ArgList[0]); } static void p_nick(from, ArgList) u_char *from, **ArgList; { int one_prints = 0, its_me = 0; u_char *chan; u_char *line; int flag; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_CRAP); line = ArgList[0]; if (my_stricmp(from, get_server_nickname(parsing_server_index)) == 0){ if (parsing_server_index == primary_server) malloc_strcpy(&nickname, line); set_server_nickname(parsing_server_index, line); its_me = 1; } save_message_from(); if (flag != IGNORED) { for (chan = walk_channels(from, 1, parsing_server_index); chan; chan = walk_channels(from, 0, -1)) { message_from(chan, LOG_CRAP); if (do_hook(CHANNEL_NICK_LIST, "%s %s %s", chan, from, line)) one_prints = 1; } if (one_prints) { if (its_me) message_from((u_char *) 0, LOG_CRAP); else message_from(what_channel(from, parsing_server_index), LOG_CRAP); if (do_hook(NICKNAME_LIST, "%s %s", from, line)) say("%s is now known as %s", from, line); } } rename_nick(from, line, parsing_server_index); if (my_stricmp(from, line)) { message_from((u_char *) 0, LOG_CURRENT); notify_mark(from, 0, 0); notify_mark(line, 1, 0); } restore_message_from(); } static void p_mode(from, ArgList) u_char *from, **ArgList; { u_char *channel; u_char *line; int flag; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_CRAP); PasteArgs(ArgList, 1); channel = ArgList[0]; line = ArgList[1]; save_message_from(); message_from(channel, LOG_CRAP); if (channel && line) { if (is_channel(channel)) { if (flag != IGNORED && do_hook(MODE_LIST, "%s %s %s", from, channel, line)) say("Mode change \"%s\" on channel %s by %s", line, channel, from); update_channel_mode(channel, parsing_server_index, line); } else { if (flag != IGNORED && do_hook(MODE_LIST, "%s %s %s", from, channel, line)) say("Mode change \"%s\" for user %s by %s", line, channel, from); update_user_mode(line); } update_all_status(); } restore_message_from(); } static void p_kick(from, ArgList) u_char *from, **ArgList; { u_char *channel, *who, *comment; if (!from) return; channel = ArgList[0]; who = ArgList[1]; comment = ArgList[2]; if (channel && who) { save_message_from(); message_from(channel, LOG_CRAP); if (my_stricmp(who, get_server_nickname(parsing_server_index)) == 0) { if (comment && *comment) { if (do_hook(KICK_LIST, "%s %s %s %s", who, from, channel, comment)) say("You have been kicked off channel %s by %s (%s)", channel, from, comment); } else { if (do_hook(KICK_LIST, "%s %s %s", who, from, channel)) say("You have been kicked off channel %s by %s", channel, from); } remove_channel(channel, parsing_server_index); update_all_status(); } else { if (comment && *comment) { if (do_hook(KICK_LIST, "%s %s %s %s", who, from, channel, comment)) say("%s has been kicked off channel %s by %s (%s)", who, channel, from, comment); } else { if (do_hook(KICK_LIST, "%s %s %s", who, from, channel)) say("%s has been kicked off channel %s by %s", who, channel, from); } remove_from_channel(channel, who, parsing_server_index); } restore_message_from(); } } static void p_part(from, ArgList) u_char *from, **ArgList; { u_char *channel; u_char *comment; int flag; if (!from) return; flag = double_ignore(from, FromUserHost, IGNORE_CRAP); channel = ArgList[0]; if (!is_on_channel(channel, parsing_server_index, from)) return; comment = ArgList[1]; if (!comment) comment = empty_string; in_on_who = 1; if (flag != IGNORED) { save_message_from(); message_from(channel, LOG_CRAP); if (do_hook(LEAVE_LIST, "%s %s %s", from, channel, comment)) { if (comment && *comment != '\0') say("%s has left channel %s (%s)", from, channel, comment); else say("%s has left channel %s", from, channel); } restore_message_from(); } if (my_stricmp(from, get_server_nickname(parsing_server_index)) == 0) remove_channel(channel, parsing_server_index); else remove_from_channel(channel, from, parsing_server_index); in_on_who = 0; } /* * parse_server: parses messages from the server, doing what should be done * with them */ void parse_server(line) u_char *line; { server_list[parsing_server_index].parse_server(line); } void irc2_parse_server(line) u_char *line; { u_char *from, *comm, *end, *copy = (u_char *) 0; int numeric; u_char **ArgList; u_char *TrueArgs[MAXPARA + 1]; if ((u_char *) 0 == line) return; end = my_strlen(line) + line; if (*--end == '\n') *end-- = '\0'; if (*end == '\r') *end-- = '\0'; if (*line == ':') { if (!do_hook(RAW_IRC_LIST, "%s", line + 1)) return; } else if (!do_hook(RAW_IRC_LIST, "%s %s", "*", line)) return; malloc_strcpy(©, line); ArgList = TrueArgs; BreakArgs(copy, &from, ArgList); if (!(comm = (*ArgList++))) return; /* Empty line from server - ByeBye */ /* * XXX!!! * this should fail on '1xxx'!!! */ if (0 != (numeric = my_atoi(comm))) numbered_command(from, numeric, ArgList); else if (my_strcmp(comm, "NAMREPLY") == 0) funny_namreply(from, ArgList); else if (my_strcmp(comm, "WHOREPLY") == 0) whoreply(from, ArgList); else if (my_strcmp(comm, "NOTICE") == 0) parse_notice(from, ArgList); /* everything else is handled locally */ else if (my_strcmp(comm, "PRIVMSG") == 0) p_privmsg(from, ArgList); else if (my_strcmp(comm, "JOIN") == 0) p_channel(from, ArgList); else if (my_strcmp(comm, "PART") == 0) p_part(from, ArgList); else if (my_strcmp(comm, "CHANNEL") == 0) p_channel(from, ArgList); else if (my_strcmp(comm, "MSG") == 0) /*p_msgcmd(from, ArgList)*/; else if (my_strcmp(comm, "QUIT") == 0) p_quit(from, ArgList); else if (my_strcmp(comm, "WALL") == 0) p_wall(from, ArgList); else if (my_strcmp(comm, "WALLOPS") == 0) p_wallops(from, ArgList); else if (my_strcmp(comm, "LINREPLY") == 0) p_linreply(ArgList); else if (my_strcmp(comm, "PING") == 0) p_ping(ArgList); else if (my_strcmp(comm, "TOPIC") == 0) p_topic(from, ArgList); else if (my_strcmp(comm, "PONG") == 0) p_pong(from, ArgList); else if (my_strcmp(comm, "INVITE") == 0) p_invite(from, ArgList); else if (my_strcmp(comm, "NICK") == 0) p_nick(from, ArgList); else if (my_strcmp(comm, "KILL") == 0) p_server_kill(from, ArgList); else if (my_strcmp(comm, "MODE") == 0) p_mode(from, ArgList); else if (my_strcmp(comm, "KICK") == 0) p_kick(from, ArgList); else if (my_strcmp(comm, "ERROR") == 0) p_error(from, ArgList); else if (my_strcmp(comm, "ERROR:") == 0) /* Server bug makes this a must */ p_error(from, ArgList); else { PasteArgs(ArgList, 0); if (from) say("Odd server stuff: \"%s %s\" (%s)", comm, ArgList[0], from); else say("Odd server stuff: \"%s %s\"", comm, ArgList[0]); } new_free(©); } .