/*
* 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
* Modified Colten Edwards 1997
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "irc.h"
#include "server.h"
#include "names.h"
#include "vars.h"
#include "ctcp.h"
#include "hook.h"
#include "commands.h"
#include "ignore.h"
#include "whois.h"
#include "lastlog.h"
#include "input.h"
#include "notice.h"
#include "ircaux.h"
#include "funny.h"
#include "input.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"
#include "status.h"
#include "list.h"
#include "misc.h"
#include "whowas.h"
#include "timer.h"
#include "hash.h"
#include "fset.h"
#include "tcommand.h"
#define space ' '
static void strip_modes(char *, char *, char *);
extern char *do_nslookup(char *);
extern char *random_str(int, int);
char *last_split_server = NULL;
int in_server_ping = 0;
extern char *mircansi(char *);
#ifdef COMPRESS_MODES
extern char *compress_modes(int, char *, char *);
#endif
/* TODO: this needs to be someplace better */
/* in cmd_orignick.c */
void check_orig_nick(char *nick);
/*
* joined_nick: the nickname of the last person who joined the current
* channel
*/
char *joined_nick = NULL;
/* public_nick: nick of the last person to send a message to your channel */
char *public_nick = NULL;
/* User and host information from server 2.7 */
char *FromUserHost = empty_str;
/* doing a PRIVMSG */
int doing_privmsg = 0;
int chan_who = 0;
/* returns 1 if the ban is on the channel already, 0 if not */
BanList *ban_is_on_channel(char *ban, struct channel *chan)
{
register BanList *bans;
for (bans = chan->bans; bans; bans = bans->next) {
if (match(bans->ban, ban) || match(ban, bans->ban))
return bans;
else if (!my_stricmp(bans->ban, ban))
return bans;
}
return NULL;
}
void fake(void)
{
bitchsay("--- Fake Message recieved!!! ---");
return;
}
char *PasteArgs(char **Args, int StartPoint)
{
int i;
for (; StartPoint; Args++, StartPoint--)
if (!*Args)
return NULL;
for (i = 0; Args[i] && Args[i + 1]; i++)
Args[i][strlen(Args[i])] = ' ';
Args[1] = NULL;
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.
*/
int BreakArgs(char *Input, char **Sender, char **OutPut, int ig_sender)
{
int ArgCount = 0;
/*
* The RFC describes it fully, but in a short form, a line looks like:
* [:sender[!user@host]] COMMAND ARGUMENT [[:]ARGUMENT]{0..14}
*/
/*
* Look to see if the optional :sender is present.
*/
if (!ig_sender) {
if (*Input == ':') {
*Sender = ++Input;
while (*Input && *Input != space)
Input++;
if (*Input == space)
*Input++ = 0;
/*
* Look to see if the optional !user@host is present.
*/
FromUserHost = *Sender;
while (*FromUserHost && *FromUserHost != '!')
FromUserHost++;
if (*FromUserHost == '!')
*FromUserHost++ = 0;
}
/*
* No sender present.
*/
else
*Sender = FromUserHost = empty_str;
}
/*
* Now we go through the argument list...
*/
for (;;) {
while (*Input && *Input == space)
Input++;
if (!*Input)
break;
if (*Input == ':') {
OutPut[ArgCount++] = ++Input;
break;
}
OutPut[ArgCount++] = Input;
if (ArgCount >= MAXPARA)
break;
while (*Input && *Input != space)
Input++;
if (*Input == space)
*Input++ = 0;
}
OutPut[ArgCount] = NULL;
return ArgCount;
}
/* in response to a TOPIC message from the server */
static void p_topic(char *from, char **ArgList)
{
struct channel *tmp;
if (!ArgList[1]) {
fake();
return;
}
tmp = lookup_channel(ArgList[0], from_server, CHAN_NOUNLINK);
malloc_strcpy(&tmp->topic, ArgList[1]);
if (check_ignore(from, FromUserHost, tmp->channel, IGNORE_TOPICS | IGNORE_CRAP, NULL) != IGNORED) {
message_from(ArgList[0], LOG_CRAP);
if (do_hook(TOPIC_LIST, "%s %s %s", from, ArgList[0], ArgList[1])) {
if (ArgList[1] && *ArgList[1]) {
if (get_format(FORMAT_TOPIC_CHANGE_HEADER_FSET))
put_it("%s",
convert_output_format(get_format(FORMAT_TOPIC_CHANGE_HEADER_FSET), "%s %s %s %s", update_clock(GET_TIME),
from, ArgList[0], ArgList[1]));
put_it("%s",
convert_output_format(get_format(FORMAT_TOPIC_CHANGE_FSET), "%s %s %s %s", update_clock(GET_TIME), from,
ArgList[0], ArgList[1]));
} else
put_it("%s",
convert_output_format(get_format(FORMAT_TOPIC_UNSET_FSET), "%s %s %s", update_clock(GET_TIME), from,
ArgList[0]));
}
message_from(NULL, LOG_CRAP);
}
update_all_status(curr_scr_win, NULL, 0);
}
static void p_wallops(char *from, char **ArgList)
{
char *line;
int from_server = strchr(from, '.') ? 1 : 0;
if (!(line = PasteArgs(ArgList, 0))) {
fake();
return;
}
if (from_server || check_flooding(from, WALLOP_FLOOD, line, NULL)) {
/* The old server check, don't use the whois stuff for servers */
int level;
char *high;
switch (check_ignore(from, FromUserHost, NULL, IGNORE_WALLOPS, NULL)) {
case (IGNORED):
return;
case (HIGHLIGHTED):
high = highlight_char;
break;
default:
high = empty_str;
break;
}
message_from(from, LOG_WALLOP);
level = set_lastlog_msg_level(LOG_WALLOP);
if (do_hook(WALLOP_LIST, "%s %c %s", from, from_server ? 'S' : '*', line))
put_it("%s", convert_output_format(get_format(from_server ? FORMAT_WALLOP_FSET : FORMAT_WALL_FSET),
"%s %s %s %s", update_clock(GET_TIME), from, from_server ? "!" : "*", line));
if (beep_on_level & LOG_WALLOP)
beep_em(1);
set_lastlog_msg_level(level);
message_from(NULL, LOG_CRAP);
}
}
void whoreply(char *from, char **ArgList)
{
static char format[40];
static int last_width = -1;
int ok = 1, voice = 0, opped = 0;
char *channel, *user, *host, *server, *nick, *stat, *name;
struct channel *chan = NULL;
char buf_data[BIG_BUFFER_SIZE + 1];
if (!ArgList[5])
return;
if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR)) {
if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0)
snprintf(format, 39, "%%-%u.%us \002%%-9s\002 %%-3s %%s@%%s (%%s)",
(unsigned char) last_width, (unsigned char) last_width);
else
strcpy(format, "%s\t\002%-9s\002 %-3s %s@%s (%s)");
}
channel = ArgList[0];
user = ArgList[1];
host = ArgList[2];
server = ArgList[3];
nick = ArgList[4];
stat = ArgList[5];
name = ArgList[6];
PasteArgs(ArgList, 6);
message_from(channel, LOG_CRAP);
*buf_data = 0;
strmopencat(buf_data, BIG_BUFFER_SIZE, user, "@", host, NULL);
voice = (strchr(stat, '+') != NULL);
opped = (strchr(stat, '@') != NULL);
if (*stat == 'S') { /* this only true for the header WHOREPLY */
char buffer[BIG_BUFFER_SIZE + 1];
channel = "Channel";
snprintf(buffer, BIG_BUFFER_SIZE, "%s %s %s %s %s %s %s", channel, nick, stat, user, host, server, name);
if (do_hook(WHO_LIST, "%s", buffer))
put_it("%s",
convert_output_format(get_format(FORMAT_WHO_FSET), "%s %s %s %s %s %s %s", channel, nick, stat, user, host, server,
name));
message_from(NULL, LOG_CRAP);
return;
}
if (who_mask) {
if (who_mask & WHO_HERE)
ok = ok && (*stat == 'H');
if (who_mask & WHO_AWAY)
ok = ok && (*stat == 'G');
if (who_mask & WHO_OPS)
ok = ok && (*(stat + 1) == '*');
if (who_mask & WHO_LUSERS)
ok = ok && (*(stat + 1) != '*');
if (who_mask & WHO_CHOPS)
ok = ok && ((*(stat + 1) == '@') || (*(stat + 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 (ok) {
char buffer[BIG_BUFFER_SIZE + 1];
snprintf(buffer, BIG_BUFFER_SIZE, "%s %s %s %s %s %s %s", channel, nick, stat, user, host, server, name);
chan = add_to_channel(channel, nick, from_server, opped, voice, buf_data, server, stat);
if (do_hook(WHO_LIST, "%s", buffer)) {
if (!get_int_var(SHOW_WHO_HOPCOUNT_VAR))
next_arg(name, &name);
put_it("%s",
convert_output_format(get_format(FORMAT_WHO_FSET), "%s %s %s %s %s %s %s", channel, nick, stat, user, host, server,
name));
}
}
/*
else if ((who_mask && WHO_KILL) && !ok)
{
put_it("%s", convert_output_format("$G No such match for /whokill", NULL, NULL));
}
*/
message_from(NULL, LOG_CRAP);
}
static void p_privmsg(char *from, char **Args)
{
int level, list_type, flood_type, log_type, no_flood = 1, do_beep = 1;
unsigned char ignore_type;
char *ptr = NULL, *to;
char *high;
struct channel *channel = NULL;
struct nick_list *tmpnick = NULL;
if (!from)
return;
PasteArgs(Args, 1);
to = Args[0];
ptr = Args[1];
if (!to || !ptr) {
fake();
return;
}
doing_privmsg = 1;
if (is_channel(to) && im_on_channel(to)) {
message_from(to, LOG_MSG);
malloc_strcpy(&public_nick, from);
log_type = LOG_PUBLIC;
ignore_type = IGNORE_PUBLIC;
flood_type = PUBLIC_FLOOD;
if (!is_on_channel(to, from_server, from))
list_type = PUBLIC_MSG_LIST;
else {
if (is_current_channel(to, from_server, 0))
list_type = PUBLIC_LIST;
else
list_type = PUBLIC_OTHER_LIST;
channel = lookup_channel(to, from_server, CHAN_NOUNLINK);
if (channel)
tmpnick = find_nicklist_in_channellist(from, channel, 0);
}
} else {
message_from(from, LOG_MSG);
flood_type = MSG_FLOOD;
if (my_stricmp(to, get_server_nickname(from_server))) {
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;
}
}
switch (check_ignore(from, FromUserHost, to, ignore_type, ptr)) {
case IGNORED:
if ((list_type == MSG_LIST) && get_int_var(SEND_IGNORE_MSG_VAR))
send_to_server(SERVER(from_server), "NOTICE %s :%s is ignoring you", from, get_server_nickname(from_server));
doing_privmsg = 0;
return;
case HIGHLIGHTED:
high = highlight_char;
break;
case CHANNEL_GREP:
high = highlight_char;
break;
default:
high = empty_str;
break;
}
ptr = do_ctcp(from, to, ptr);
if (!ptr || !*ptr) {
doing_privmsg = 0;
return;
}
level = set_lastlog_msg_level(log_type);
if (flood_type == PUBLIC_FLOOD) {
int blah = 0;
if (is_other_flood(channel, tmpnick, PUBLIC_FLOOD, &blah)) {
no_flood = 0;
flood_prot(tmpnick->nick, FromUserHost, "PUBLIC", flood_type, get_int_var(PUBFLOOD_TIME_VAR), channel->channel);
}
} else
no_flood = check_flooding(from, flood_type, ptr, NULL);
{
switch (list_type) {
case PUBLIC_MSG_LIST:
logmsg(LOG_PUBLIC, from, ptr, 0);
if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr))
put_it("%s",
convert_output_format(get_format(FORMAT_PUBLIC_MSG_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from,
FromUserHost, to, get_int_var(MIRCS_VAR) ? mircansi(ptr) : ptr));
break;
case MSG_GROUP_LIST:
logmsg(LOG_PUBLIC, from, ptr, 0);
if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr))
put_it("%s",
convert_output_format(get_format(FORMAT_MSG_GROUP_FSET), "%s %s %s %s", update_clock(GET_TIME), from, to,
get_int_var(MIRCS_VAR) ? mircansi(ptr) : ptr));
break;
case MSG_LIST:
{
if (!no_flood)
break;
malloc_strcpy(&recv_nick, from);
if (away_set) {
do_beep = 0;
beep_em(get_int_var(BEEP_WHEN_AWAY_VAR));
set_int_var(MSGCOUNT_VAR, get_int_var(MSGCOUNT_VAR) + 1);
}
logmsg(LOG_MSG, from, ptr, 0);
addtabkey(from, "msg");
if (do_hook(list_type, "%s %s", from, ptr))
put_it("%s",
convert_output_format(get_format(FORMAT_MSG_FSET), "%s %s %s %s", update_clock(GET_TIME), from,
FromUserHost, get_int_var(MIRCS_VAR) ? mircansi(ptr) : ptr));
if (from_server > -1 && get_server_away(from_server) && get_int_var(SEND_AWAY_MSG_VAR)) {
send_to_server(SERVER(from_server), "NOTICE %s :%s", from,
stripansicodes(convert_output_format
(get_format(FORMAT_SEND_AWAY_FSET), "%l %l %s", time(NULL),
server_list[from_server].awaytime, get_int_var(MSGLOG_VAR) ? "On" : "Off")));
}
break;
}
case PUBLIC_LIST:{
logmsg(LOG_PUBLIC, from, ptr, 0);
if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr))
put_it("%s",
convert_output_format(get_format(FORMAT_PUBLIC_FSET), "%s %s %s %s", update_clock(GET_TIME), from, to,
get_int_var(MIRCS_VAR) ? mircansi(ptr) : ptr));
break;
}
case PUBLIC_OTHER_LIST:{
logmsg(LOG_PUBLIC, from, ptr, 0);
if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr))
put_it("%s",
convert_output_format(get_format(FORMAT_PUBLIC_OTHER_FSET), "%s %s %s %s", update_clock(GET_TIME), from, to,
get_int_var(MIRCS_VAR) ? mircansi(ptr) : ptr));
break;
} /* case */
} /* switch */
}
if (beep_on_level & log_type && do_beep)
beep_em(1);
set_lastlog_msg_level(level);
message_from(NULL, LOG_CRAP);
doing_privmsg = 0;
}
static void p_quit(char *from, char **ArgList)
{
int one_prints = 0;
char *chan = NULL;
char *Reason;
int netsplit = 0;
int ignore;
PasteArgs(ArgList, 0);
if (ArgList[0]) {
Reason = ArgList[0];
netsplit = check_split(from, Reason, chan);
} else
Reason = "?";
ignore = check_ignore(from, FromUserHost, NULL, (netsplit ? IGNORE_SPLITS : IGNORE_QUITS) | IGNORE_ALL, NULL);
for (chan = walk_channels(from, 1, from_server); chan; chan = walk_channels(from, 0, -1)) {
if (ignore != IGNORED) {
message_from(chan, LOG_CRAP);
if (do_hook(CHANNEL_SIGNOFF_LIST, "%s %s %s", chan, from, Reason))
one_prints = 1;
message_from(NULL, LOG_CURRENT);
}
}
if (one_prints) {
chan = what_channel(from, from_server);
ignore = check_ignore(from, FromUserHost, chan, (netsplit ? IGNORE_SPLITS : IGNORE_QUITS) | IGNORE_ALL, NULL);
message_from(chan, LOG_CRAP);
if ((ignore != IGNORED) && do_hook(SIGNOFF_LIST, "%s %s", from, Reason) && !netsplit)
put_it("%s",
convert_output_format(get_format(FORMAT_CHANNEL_SIGNOFF_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from,
FromUserHost, chan, Reason));
message_from(NULL, LOG_CURRENT);
}
if (!netsplit)
check_orig_nick(from);
notify_mark(from, NULL, NULL, 0);
remove_from_channel(NULL, from, from_server, netsplit, Reason);
message_from(NULL, LOG_CRAP);
update_all_status(curr_scr_win, NULL, 0);
}
static void p_pong(char *from, char **ArgList)
{
int is_server = 0;
int i;
if (!ArgList[0])
return;
is_server = match("*.*", ArgList[0]);
if (in_server_ping && is_server) ;
{
int old_from_server = from_server;
for (i = 0; i < number_of_servers; i++) {
if ((!my_stricmp(ArgList[0], get_server_name(i)) || !my_stricmp(ArgList[0], get_server_itsname(i)))
&& is_server_connected(i)) {
int old_lag = server_list[i].lag;
from_server = i;
server_list[i].lag = time(NULL) - server_list[i].lag_time;
in_server_ping--;
if (old_lag != server_list[i].lag)
status_update(1);
from_server = old_from_server;
return;
}
}
from_server = old_from_server;
}
if (check_ignore(from, FromUserHost, NULL, IGNORE_PONGS | IGNORE_CRAP, NULL) != IGNORED) {
if (!is_server)
return;
if (!ArgList[1])
say("%s: PONG received from %s", ArgList[0], from);
else
say("%s: PING received from %s %s", ArgList[0], from, ArgList[1]);
}
}
static void p_error(char *from, char **ArgList)
{
PasteArgs(ArgList, 0);
if (!ArgList[0]) {
fake();
return;
}
say("%s", ArgList[0]);
}
static void p_channel(char *from, char **ArgList)
{
char *channel;
char *user, *host;
struct channel *chan = NULL;
struct whowas_list *whowas = NULL;
int its_me = 0;
if (!strcmp(ArgList[0], "0")) {
fake();
return;
}
channel = ArgList[0];
message_from(channel, LOG_CRAP);
malloc_strcpy(&joined_nick, from);
if (!my_stricmp(from, get_server_nickname(from_server))) {
int refnum;
Window *old_window = curr_scr_win;
int switched = 0;
if (!in_join_list(channel, from_server))
add_to_join_list(channel, from_server, curr_scr_win->refnum);
else {
if (curr_scr_win->refnum != (refnum = get_win_from_join_list(channel, from_server))) {
switched = 1;
set_current_window(get_window_by_refnum(refnum));
}
}
if (*channel != '+')
send_to_server(SERVER(from_server), "MODE %s\r\nMODE %s b", channel, channel, channel);
(void) do_hook(JOIN_ME_LIST, "%s", channel);
its_me = 1;
chan = add_channel(channel, from_server);
if (*channel == '+') {
got_info(channel, from_server, GOTBANS);
got_info(channel, from_server, GOTMODE);
}
if (switched)
set_current_window(old_window);
} else {
int op = 0, vo = 0;
char *c;
/*
* Workaround for gratuitous protocol change in ef2.9
*/
if ((c = strchr(channel, '\007'))) {
for (*c++ = 0; *c; c++) {
if (*c == 'o')
op = 1;
else if (*c == 'v')
vo = 1;
}
}
chan = add_to_channel(channel, from, from_server, op, vo, FromUserHost, NULL, NULL);
}
flush_mode_all(chan);
user = m_strdup(FromUserHost);
host = strchr(user, '@');
*host++ = '\0';
if (check_ignore(from, FromUserHost, channel, IGNORE_JOINS | IGNORE_CRAP, NULL) != IGNORED && chan) {
irc_server *irc_serv = NULL;
char *tmp2 = NULL;
if (get_int_var(AUTO_NSLOOKUP_VAR) && isdigit(*(host + strlen(host) - 1)))
tmp2 = do_nslookup(host);
message_from(channel, LOG_CRAP);
if ((whowas = check_whosplitin_buffer(from, FromUserHost, channel, 0)) && (irc_serv = check_split_server(whowas->server1))) {
if (do_hook(LLOOK_JOIN_LIST, "%s %s", irc_serv->name, irc_serv->link))
put_it("%s",
convert_output_format(get_format(FORMAT_NETJOIN_FSET), "%s %s %s %d", update_clock(GET_TIME), irc_serv->name,
irc_serv->link, 0));
remove_split_server(whowas->server1);
}
if (do_hook(JOIN_LIST, "%s %s %s", from, channel, tmp2 ? tmp2 : FromUserHost ? FromUserHost : "UnKnown")) {
put_it("%s",
convert_output_format(get_format(FORMAT_JOIN_FSET), "%s %s %s %s", update_clock(GET_TIME), from,
tmp2 ? tmp2 : FromUserHost ? FromUserHost : "UnKnown", channel));
}
message_from(NULL, LOG_CRAP);
}
set_input_prompt(curr_scr_win, get_string_var(INPUT_PROMPT_VAR), 0);
update_all_status(curr_scr_win, NULL, 0);
notify_mark(from, user, host, 1);
new_free(&user);
}
static void p_invite(char *from, char **ArgList)
{
char *high;
switch (check_ignore(from, FromUserHost, ArgList[1] ? ArgList[1] : NULL, IGNORE_INVITES, NULL)) {
case IGNORED:
if (get_int_var(SEND_IGNORE_MSG_VAR))
send_to_server(SERVER(from_server), "NOTICE %s :%s is ignoring you", from, get_server_nickname(from_server));
return;
case HIGHLIGHTED:
high = highlight_char;
break;
default:
high = empty_str;
break;
}
if (ArgList[0] && ArgList[1]) {
struct channel *chan = NULL;
struct whowas_chan_list *w_chan = NULL;
message_from(from, LOG_CRAP);
malloc_strcpy(&invite_channel, ArgList[1]);
if (check_flooding(from, INVITE_FLOOD, ArgList[1], NULL) && do_hook(INVITE_LIST, "%s %s", from, ArgList[1])) {
put_it("%s", convert_output_format(get_format(FORMAT_INVITE_FSET), "%s %s %s", update_clock(GET_TIME), from, ArgList[1]));
}
if (!(chan = lookup_channel(invite_channel, from_server, 0)))
if ((w_chan = check_whowas_chan_buffer(invite_channel, 0)))
chan = w_chan->channellist;
if (chan && get_int_var(AUTO_REJOIN_VAR) && invite_channel) {
if (!in_join_list(invite_channel, from_server))
send_to_server(SERVER(from_server), "JOIN %s %s", invite_channel, ArgList[2] ? ArgList[2] : "");
}
malloc_strcpy(&recv_nick, from);
}
}
static void p_silence(char *from, char **ArgList)
{
char *target = ArgList[0];
char *mag = target++;
if (do_hook(SILENCE_LIST, "%c %s", *mag, target))
put_it("%s", convert_output_format(get_format(FORMAT_SILENCE_FSET), "%s %c %s", update_clock(GET_TIME), *mag, target));
}
static void p_kill(char *from, char **ArgList)
{
char sc[20];
int port;
int local = 0;
port = get_server_port(from_server);
if (ArgList[1] && strstr(ArgList[1], get_server_name(from_server)))
if (!strchr(from, '.'))
local = 1;
snprintf(sc, 19, "+%i %d", from_server, port);
close_server(from_server, empty_str);
clean_whois_queue();
window_check_servers();
set_input_prompt(curr_scr_win, get_string_var(INPUT_PROMPT_VAR), 0);
if (strchr(from, '.')) {
say("Server [%s] has rejected you (probably due to a nick collision)", from);
t_parse_command("SERVER", NULL);
} else {
if (local && get_int_var(NEXT_SERVER_ON_LOCAL_KILL_VAR)) {
int i = from_server + 1;
if (i >= number_of_servers)
i = 0;
snprintf(sc, 19, "+%i", i);
from_server = -1;
}
if (do_hook(DISCONNECT_LIST, "Killed by %s (%s)", from, ArgList[1] ? ArgList[1] : "(No Reason Given)"))
put_it("%s",
convert_output_format(get_format(FORMAT_KILL_FSET), "%s %s", update_clock(GET_TIME),
ArgList[1] ? ArgList[1] : "You have been Killed"));
if (get_int_var(AUTO_RECONNECT_VAR))
t_parse_command("SERVER", NULL);
}
update_all_status(curr_scr_win, NULL, 0);
}
static void p_ping(char **ArgList)
{
PasteArgs(ArgList, 0);
send_to_server(SERVER(from_server), "PONG %s", ArgList[0]);
}
static void p_nick(char *from, char **ArgList)
{
int one_prints = 0, ign = 0, its_me = 0;
struct channel *chan;
char *line;
line = ArgList[0];
if (!my_stricmp(from, get_server_nickname(from_server))) {
accept_server_nickname(from_server, line);
its_me = 1;
user_changing_nickname = 0;
}
ign = check_ignore(from, FromUserHost, NULL, IGNORE_NICKS | IGNORE_CRAP, NULL);
for (chan = server_list[from_server].chan_list; chan; chan = chan->next) {
message_from(chan->channel, LOG_CRAP);
if (ign != IGNORED && do_hook(CHANNEL_NICK_LIST, "%s %s %s", chan->channel, from, line))
one_prints = 1;
}
if (one_prints) {
if (its_me) {
message_from(NULL, LOG_CRAP);
} else
message_from(what_channel(from, from_server), LOG_CRAP);
if (ign != IGNORED && do_hook(NICKNAME_LIST, "%s %s", from, line))
put_it("%s",
convert_output_format(get_format
(its_me ? FORMAT_NICKNAME_USER_FSET : im_on_channel(what_channel(from, from_server)) ?
FORMAT_NICKNAME_FSET : FORMAT_NICKNAME_OTHER_FSET), "%s %s %s %s", update_clock(GET_TIME),
from, "-", line));
}
rename_nick(from, line, from_server);
if (!its_me) {
char *user, *host;
user = m_strdup(FromUserHost);
host = strchr(user, '@');
*host++ = '\0';
notify_mark(from, user, host, 0);
notify_mark(line, user, host, 1);
new_free(&user);
}
}
static void p_mode(char *from, char **ArgList)
{
char *channel;
char *line;
int flag;
struct channel *chan = NULL;
char buffer[BIG_BUFFER_SIZE + 1];
char *smode;
#ifdef COMPRESS_MODES
char *tmpbuf = NULL;
#endif
PasteArgs(ArgList, 1);
channel = ArgList[0];
line = ArgList[1];
smode = strchr(from, '.');
flag = check_ignore(from, FromUserHost, channel, (smode ? IGNORE_SMODES : IGNORE_MODES) | IGNORE_CRAP, NULL);
message_from(channel, LOG_CRAP);
if (channel && line) {
strcpy(buffer, line);
if (get_int_var(MODE_STRIPPER_VAR))
strip_modes(from, channel, line);
if (is_channel(channel)) {
#ifdef COMPRESS_MODES
chan = (struct channel *) find_in_list((struct list **) &server_list[from_server].chan_list, channel, 0);
if (get_int_var(COMPRESS_MODES_VAR)) {
tmpbuf = compress_modes(from_server, channel, line);
if (tmpbuf)
strcpy(line, tmpbuf);
else
goto end_p_mode;
}
#endif
/* CDE handle mode protection here instead of later */
update_channel_mode(from, channel, from_server, buffer, chan);
if (flag != IGNORED && do_hook(MODE_LIST, "%s %s %s", from, channel, line))
put_it("%s",
convert_output_format(get_format(smode ? FORMAT_SMODE_FSET : FORMAT_MODE_FSET), "%s %s %s %s %s",
update_clock(GET_TIME), from, smode ? "*" : FromUserHost, channel, line));
} else {
if (flag != IGNORED && do_hook(MODE_LIST, "%s %s %s", from, channel, line)) {
if (!my_stricmp(from, channel)) {
if (!my_stricmp(from, get_server_nickname(from_server)))
put_it("%s",
convert_output_format(get_format(FORMAT_USERMODE_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from,
"*", channel, line));
else
put_it("%s",
convert_output_format(get_format(FORMAT_USERMODE_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from,
smode ? "*" : FromUserHost, channel, line));
} else
put_it("%s",
convert_output_format(get_format(FORMAT_MODE_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from,
smode ? "*" : FromUserHost, channel, line));
}
update_user_mode(line);
}
#ifdef COMPRESS_MODES
end_p_mode:
#endif
update_all_status(curr_scr_win, NULL, 0);
}
message_from(NULL, LOG_CRAP);
}
static void strip_modes(char *from, char *channel, char *line)
{
char *mode;
char *pointer;
char mag = '+'; /* XXXX Bogus */
char *copy = NULL;
#ifdef __GNUC__
char free_copy[strlen(line) + 1];
strcpy(free_copy, line);
#else
char *free_copy = NULL;
malloc_strcpy(&free_copy, line);
#endif
copy = free_copy;
mode = next_arg(copy, ©);
if (is_channel(channel)) {
for (pointer = mode; *pointer; pointer++) {
char c = *pointer;
switch (c) {
case '+':
case '-':
mag = c;
break;
case 'l':
if (mag == '+')
do_hook(MODE_STRIPPED_LIST, "%s %s %c%c %s", from, channel, mag, c, next_arg(copy, ©));
else
do_hook(MODE_STRIPPED_LIST, "%s %s %c%c", from, channel, mag, c);
break;
case 'a':
case 'i':
case 'm':
case 'n':
case 'p':
case 's':
case 't':
do_hook(MODE_STRIPPED_LIST, "%s %s %c%c", from, channel, mag, c);
break;
case 'b':
case 'k':
case 'o':
case 'v':
do_hook(MODE_STRIPPED_LIST, "%s %s %c%c %s", from, channel, mag, c, next_arg(copy, ©));
break;
}
}
} else
/* User mode */
{
for (pointer = mode; *pointer; pointer++) {
char c = *pointer;
switch (c) {
case '+':
case '-':
mag = c;
break;
default:
do_hook(MODE_STRIPPED_LIST, "%s %s %c%c", from, channel, mag, c);
break;
}
}
}
#ifndef __GNUC__
new_free(&free_copy);
#endif
}
static void p_kick(char *from, char **ArgList)
{
char *channel, *who, *comment;
char *chankey = NULL;
struct channel *chan = NULL;
struct nick_list *tmpnick = NULL;
int t = 0;
channel = ArgList[0];
who = ArgList[1];
comment = ArgList[2] ? ArgList[2] : "(no comment)";
if ((chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
tmpnick = find_nicklist_in_channellist(from, chan, 0);
message_from(channel, LOG_CRAP);
if (channel && who && chan) {
if (!my_stricmp(who, get_server_nickname(from_server))) {
Window *window = chan->window;
if (chan->key)
malloc_strcpy(&chankey, chan->key);
if (get_int_var(AUTO_REJOIN_VAR)) {
send_to_server(SERVER(from_server), "JOIN %s %s", channel, chankey ? chankey : empty_str);
add_to_join_list(channel, from_server, window ? window->refnum : 0);
}
new_free(&chankey);
remove_channel(channel, from_server);
update_all_status(curr_scr_win, NULL, 0);
update_input(UPDATE_ALL);
if (do_hook(KICK_LIST, "%s %s %s %s", who, from, channel, comment ? comment : empty_str))
put_it("%s",
convert_output_format(get_format(FORMAT_KICK_USER_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from,
channel, who, comment));
} else {
int itsme = 0;
itsme = !my_stricmp(get_server_nickname(from_server), from) ? 1 : 0;
if ((check_ignore(from, FromUserHost, channel, IGNORE_KICKS | IGNORE_CRAP, NULL) != IGNORED) &&
do_hook(KICK_LIST, "%s %s %s %s", who, from, channel, comment))
put_it("%s",
convert_output_format(get_format(FORMAT_KICK_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from, channel,
who, comment));
if (!itsme) {
struct nick_list *f_nick = NULL;
f_nick = find_nicklist_in_channellist(who, chan, 0);
if (chan->chop && tmpnick && is_other_flood(chan, tmpnick, KICK_FLOOD, &t)) {
if (get_int_var(KICK_ON_KICKFLOOD_VAR) > get_int_var(DEOP_ON_KICKFLOOD_VAR))
send_to_server(SERVER(from_server), "MODE %s -o %s", chan->channel, from);
else if (!f_nick->kickcount++)
send_to_server(SERVER(from_server), "KICK %s %s :\002Mass kick detected - (%d kicks in %dsec%s)\002",
chan->channel, from, get_int_var(KICK_ON_KICKFLOOD_VAR), t, plural(t));
}
}
remove_from_channel(channel, who, from_server, 0, NULL);
}
}
update_all_status(curr_scr_win, NULL, 0);
message_from(NULL, LOG_CRAP);
}
static void p_part(char *from, char **ArgList)
{
char *channel;
if (!from || !*from)
return;
channel = ArgList[0];
PasteArgs(ArgList, 1);
message_from(channel, LOG_CRAP);
in_on_who = 1;
if ((check_ignore(from, FromUserHost, channel, IGNORE_PARTS | IGNORE_CRAP, NULL) != IGNORED) &&
do_hook(LEAVE_LIST, "%s %s %s %s", from, channel, FromUserHost, ArgList[1] ? ArgList[1] : empty_str))
put_it("%s",
convert_output_format(get_format(FORMAT_LEAVE_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from, FromUserHost,
channel, ArgList[1] ? ArgList[1] : empty_str));
if (!my_stricmp(from, get_server_nickname(from_server))) {
remove_channel(channel, from_server);
remove_from_mode_list(channel, from_server);
remove_from_join_list(channel, from_server);
set_input_prompt(curr_scr_win, get_string_var(INPUT_PROMPT_VAR), 0);
} else {
remove_from_channel(channel, from, from_server, 0, NULL);
}
update_all_status(curr_scr_win, NULL, 0);
update_input(UPDATE_ALL);
message_from(NULL, LOG_CRAP);
in_on_who = 0;
}
static void p_odd(char *from, char *comm, char **ArgList)
{
PasteArgs(ArgList, 0);
if (do_hook(ODD_SERVER_STUFF_LIST, "%s %s %s", from ? from : "*", comm, 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]);
}
}
void parse_server(char *line)
{
char *from, *comm, *end;
int numeric;
char **ArgList;
char copy[BIG_BUFFER_SIZE + 1];
char *TrueArgs[MAXPARA + 1] = { NULL };
if (!line || !*line)
return;
end = strlen(line) + line;
if (*--end == '\n')
*end-- = '\0';
if (*end == '\r')
*end-- = '\0';
if (!line || !*line)
return;
if (*line == ':') {
if (!do_hook(RAW_IRC_LIST, "%s", line + 1))
return;
} else if (!do_hook(RAW_IRC_LIST, "* %s", line))
return;
ArgList = TrueArgs;
strncpy(copy, line, BIG_BUFFER_SIZE);
FixColorAnsi(line);
BreakArgs(line, &from, ArgList, 0);
if (!(comm = (*ArgList++)) || !from || !*ArgList)
return; /* Empty line from server - ByeBye */
/*
* I reformatted these in may '96 by using the output of /stats m
* from a few busy servers. They are arranged so that the most
* common types are high on the list (to save the average number
* of compares.) I will be doing more testing in the future on
* a live client to see if this is a reasonable order.
*/
if ((numeric = atoi(comm)))
numbered_command(from, numeric, ArgList);
/* There are the core msgs for most non-numeric traffic. */
else if (!strcmp(comm, "PRIVMSG"))
p_privmsg(from, ArgList);
else if (!strcmp(comm, "JOIN"))
p_channel(from, ArgList);
else if (!strcmp(comm, "PART"))
p_part(from, ArgList);
else if (!strcmp(comm, "MODE"))
p_mode(from, ArgList);
else if (!strcmp(comm, "QUIT"))
p_quit(from, ArgList);
else if (!strcmp(comm, "NOTICE"))
parse_notice(from, ArgList);
else if (!strcmp(comm, "NICK"))
p_nick(from, ArgList);
else if (!strcmp(comm, "TOPIC"))
p_topic(from, ArgList);
else if (!strcmp(comm, "KICK"))
p_kick(from, ArgList);
else if (!strcmp(comm, "INVITE"))
p_invite(from, ArgList);
/* These are used, but not nearly as much as ones above */
else if (!strcmp(comm, "WALLOPS"))
p_wallops(from, ArgList);
else if (!strcmp(comm, "ERROR"))
p_error(from, ArgList);
else if (!strcmp(comm, "ERROR:"))
p_error(from, ArgList);
else if (!strcmp(comm, "SILENCE"))
p_silence(from, ArgList);
else if (!strcmp(comm, "KILL"))
p_kill(from, ArgList);
else if (!strcmp(comm, "PONG"))
p_pong(from, ArgList);
else if (!strcmp(comm, "PING"))
p_ping(ArgList);
/* Some kind of unrecognized/unsupported command */
else
p_odd(from, comm, ArgList);
from_server = -1;
}
syntax highlighted by Code2HTML, v. 0.9.1