void inbound_privmsg (server *serv, char *from, char *ip, char *text, int id, const message_tags_data *tags_data) { session *sess; struct User *user; char idtext[64]; gboolean nodiag = FALSE; sess = find_dialog (serv, from); if (sess || prefs.hex_gui_autoopen_dialog) { /*0=ctcp 1=priv will set hex_gui_autoopen_dialog=0 here is flud detected */ if (!sess) { if (flood_check (from, ip, serv, current_sess, 1)) /* Create a dialog session */ sess = inbound_open_dialog (serv, from, tags_data); else sess = serv->server_session; if (!sess) return; /* ?? */ } if (ip && ip[0]) set_topic (sess, ip, ip); inbound_chanmsg (serv, NULL, NULL, from, text, FALSE, id, tags_data); return; } sess = find_session_from_nick (from, serv); if (!sess) { sess = serv->front_session; nodiag = TRUE; /* We don't want it to look like a normal message in front sess */ } user = userlist_find (sess, from); if (user) { user->lasttalk = time (0); if (user->account) id = TRUE; } inbound_make_idtext (serv, idtext, sizeof (idtext), id); if (sess->type == SESS_DIALOG && !nodiag) EMIT_SIGNAL_TIMESTAMP (XP_TE_DPRIVMSG, sess, from, text, idtext, NULL, 0, tags_data->timestamp); else EMIT_SIGNAL_TIMESTAMP (XP_TE_PRIVMSG, sess, from, text, idtext, NULL, 0, tags_data->timestamp); }
void inbound_privmsg (server * serv, char *from, char *ip, char *text, int id) { session *sess; char idtext[64]; sess = find_dialog (serv, from); if (sess || prefs.autodialog) { /*0=ctcp 1=priv will set autodialog=0 here is flud detected */ if (!sess) { if (flood_check (from, ip, serv, current_sess, 1)) /* Create a dialog session */ sess = inbound_open_dialog (serv, from); else sess = serv->server_session; if (!sess) return; /* ?? */ } if (ip && ip[0]) { if (prefs.logging && sess->logfd != -1 && (!sess->topic || strcmp (sess->topic, ip))) { char tbuf[1024]; snprintf (tbuf, sizeof (tbuf), "[%s has address %s]\n", from, ip); write (sess->logfd, tbuf, strlen (tbuf)); } set_topic (sess, ip, ip); } inbound_chanmsg (serv, NULL, NULL, from, text, FALSE, id); return; } inbound_make_idtext (serv, idtext, sizeof (idtext), id); sess = find_session_from_nick (from, serv); if (!sess) { sess = serv->front_session; EMIT_SIGNAL (XP_TE_PRIVMSG, sess, from, text, idtext, NULL, 0); return; } if (sess->type == SESS_DIALOG) EMIT_SIGNAL (XP_TE_DPRIVMSG, sess, from, text, idtext, NULL, 0); else EMIT_SIGNAL (XP_TE_PRIVMSG, sess, from, text, idtext, NULL, 0); }
bool exec_client(fds c, double tdt) { char *s; s = getcmd(c); if (((c && (c->trick) && ((t_client*)c->trick)->close) || !fds_alive(c)) && (c->write || net_close(c))) return (true); if (!(c->trick) || !(((t_client*)c->trick)->_m)) return (mod_discovery(c, &s)); s = flood_check(c, s); if (scheduler_(c, tdt)) return (scheduler_dispatch(c)); else if (!scheduler_active(c) && callback_(c, s, tdt)) return (callback_handler(c, s)); else if (s && !scheduler_active(c) && (find_action(c, s) != -1)) flood_read(c); return (true); }
void inbound_action (session *sess, char *chan, char *from, char *ip, char *text, int fromme, int id) { session *def = sess; server *serv = sess->server; struct User *user; char nickchar[2] = "\000"; char idtext[64]; int privaction = FALSE; if (!fromme) { if (is_channel (serv, chan)) { sess = find_channel (serv, chan); } else { /* it's a private action! */ privaction = TRUE; /* find a dialog tab for it */ sess = find_dialog (serv, from); /* if non found, open a new one */ if (!sess && prefs.hex_gui_autoopen_dialog) { /* but only if it wouldn't flood */ if (flood_check (from, ip, serv, current_sess, 1)) sess = inbound_open_dialog (serv, from); else sess = serv->server_session; } if (!sess) { sess = find_session_from_nick (from, serv); /* still not good? */ if (!sess) sess = serv->front_session; } } } if (!sess) sess = def; if (sess != current_tab) { if (fromme) { sess->msg_said = FALSE; sess->new_data = TRUE; } else { sess->msg_said = TRUE; sess->new_data = FALSE; } } user = userlist_find (sess, from); if (user) { nickchar[0] = user->prefix[0]; user->lasttalk = time (0); } inbound_make_idtext (serv, idtext, sizeof (idtext), id); if (!fromme && !privaction) { if (is_hilight (from, text, sess, serv)) { EMIT_SIGNAL (XP_TE_HCHANACTION, sess, from, text, nickchar, idtext, 0); return; } } if (fromme) EMIT_SIGNAL (XP_TE_UACTION, sess, from, text, nickchar, idtext, 0); else if (!privaction) EMIT_SIGNAL (XP_TE_CHANACTION, sess, from, text, nickchar, idtext, 0); else if (sess->type == SESS_DIALOG) EMIT_SIGNAL (XP_TE_DPRIVACTION, sess, from, text, idtext, NULL, 0); else EMIT_SIGNAL (XP_TE_PRIVACTION, sess, from, text, idtext, NULL, 0); }
static void process_named_msg (session *sess, char *type, char *word[], char *word_eol[]) { server *serv = sess->server; char ip[128], nick[NICKLEN]; char *text, *ex; int len = strlen (type); /* fill in the "ip" and "nick" buffers */ ex = strchr (word[1], '!'); if (!ex) /* no '!', must be a server message */ { safe_strcpy (ip, word[1], sizeof (ip)); safe_strcpy (nick, word[1], sizeof (nick)); } else { safe_strcpy (ip, ex + 1, sizeof (ip)); ex[0] = 0; safe_strcpy (nick, word[1], sizeof (nick)); ex[0] = '!'; } if (len == 4) { guint32 t; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); /* this should compile to a bunch of: CMP.L, JE ... nice & fast */ switch (t) { case WORDL('J','O','I','N'): { char *chan = word[3]; if (*chan == ':') chan++; if (!serv->p_cmp (nick, serv->nick)) inbound_ujoin (serv, chan, nick, ip); else inbound_join (serv, chan, nick, ip); } return; case WORDL('K','I','C','K'): { char *kicked = word[4]; char *reason = word_eol[5]; if (*kicked) { if (*reason == ':') reason++; if (!strcmp (kicked, serv->nick)) inbound_ukick (serv, word[3], nick, reason); else inbound_kick (serv, word[3], kicked, nick, reason); } } return; case WORDL('K','I','L','L'): EMIT_SIGNAL (XP_TE_KILL, sess, nick, word_eol[5], NULL, NULL, 0); return; case WORDL('M','O','D','E'): handle_mode (serv, word, word_eol, nick, FALSE); /* modes.c */ return; case WORDL('N','I','C','K'): inbound_newnick (serv, nick, (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3], FALSE); return; case WORDL('P','A','R','T'): { char *chan = word[3]; char *reason = word_eol[4]; if (*chan == ':') chan++; if (*reason == ':') reason++; if (!strcmp (nick, serv->nick)) inbound_upart (serv, chan, ip, reason); else inbound_part (serv, chan, nick, ip, reason); } return; case WORDL('P','O','N','G'): inbound_ping_reply (serv->server_session, (word[4][0] == ':') ? word[4] + 1 : word[4], word[3]); return; case WORDL('Q','U','I','T'): inbound_quit (serv, nick, ip, (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3]); return; } goto garbage; } else if (len >= 5) { guint32 t; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); /* this should compile to a bunch of: CMP.L, JE ... nice & fast */ switch (t) { case WORDL('I','N','V','I'): if (ignore_check (word[1], IG_INVI)) return; if (word[4][0] == ':') EMIT_SIGNAL (XP_TE_INVITED, sess, word[4] + 1, nick, serv->servername, NULL, 0); else EMIT_SIGNAL (XP_TE_INVITED, sess, word[4], nick, serv->servername, NULL, 0); return; case WORDL('N','O','T','I'): { int id = FALSE; /* identified */ text = word_eol[4]; if (*text == ':') text++; if (serv->have_idmsg) { if (*text == '+') { id = TRUE; text++; } else if (*text == '-') text++; } if (!ignore_check (word[1], IG_NOTI)) inbound_notice (serv, word[3], nick, text, ip, id); } return; case WORDL('P','R','I','V'): { char *to = word[3]; int len; int id = FALSE; /* identified */ if (*to) { text = word_eol[4]; if (*text == ':') text++; if (serv->have_idmsg) { if (*text == '+') { id = TRUE; text++; } else if (*text == '-') text++; } len = strlen (text); if (text[0] == 1 && text[len - 1] == 1) /* ctcp */ { text[len - 1] = 0; text++; if (strncasecmp (text, "ACTION", 6) != 0) flood_check (nick, ip, serv, sess, 0); if (strncasecmp (text, "DCC ", 4) == 0) /* redo this with handle_quotes TRUE */ process_data_init (word[1], word_eol[1], word, word_eol, TRUE, FALSE); ctcp_handle (sess, to, nick, ip, text, word, word_eol, id); } else { if (is_channel (serv, to)) { if (ignore_check (word[1], IG_CHAN)) return; inbound_chanmsg (serv, NULL, to, nick, text, FALSE, id); } else { if (ignore_check (word[1], IG_PRIV)) return; inbound_privmsg (serv, nick, ip, text, id); } } } } return; case WORDL('T','O','P','I'): inbound_topicnew (serv, nick, word[3], (word_eol[4][0] == ':') ? word_eol[4] + 1 : word_eol[4]); return; case WORDL('W','A','L','L'): text = word_eol[3]; if (*text == ':') text++; EMIT_SIGNAL (XP_TE_WALLOPS, sess, nick, text, NULL, NULL, 0); return; } } else if (len == 3) { guint32 t; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); switch (t) { case WORDL('C','A','P','\0'): if (strncasecmp(word[4], "ACK", 3) == 0) { if (strncasecmp(word[5][0]==':' ? word[5]+1 : word[5], "identify-msg", 12) == 0) { serv->have_idmsg = TRUE; tcp_send_len(serv, "CAP END\r\n", 9); } } else if (strncasecmp(word[4], "LS", 2) == 0) { if (strstr(word_eol[5], "identify-msg") != 0) tcp_send_len(serv, "CAP REQ :identify-msg\r\n", 23); else tcp_send_len(serv, "CAP END\r\n", 9); } else if (strncasecmp(word[4], "NAK",3) == 0) { tcp_send_len(serv, "CAP END\r\n", 9); } return; } } garbage: /* unknown message */ PrintTextf (sess, "GARBAGE: %s\n", word_eol[1]); }
static void inbound_privmsg_helper(char *nickchar, char *prefixchar, char *idtext, int *is_highlight, msg_destination *action_type, session **initial_session, server *serv, char **chan, char *from, char *ip, char *text, int *from_me, int *id, const message_tags_data *tags_data) { struct User *user; session *sess = *initial_session; if (*from_me && sess == NULL) { *action_type = MSGDEST_DIRECT; sess = serv->front_session; } else if (*chan && is_channel (serv, *chan)) { *action_type = MSGDEST_CHANNEL; sess = find_channel (serv, *chan); } else if (*chan && strchr(serv->nick_prefixes, **chan) && is_channel (serv, *chan + 1)) { *action_type = MSGDEST_PREFIX; prefixchar[0] = **chan; ++*chan; sess = find_channel (serv, *chan); } else { char *target = *from_me ? *chan : from; session *userquery = find_dialog (serv, target); if (!userquery) { if (prefs.hex_gui_autoopen_dialog && flood_check (target, ip, serv, current_sess, 1)) { *action_type = MSGDEST_PRIVATE; sess = inbound_open_dialog (serv, target, tags_data); } else { *action_type = MSGDEST_DIRECT; sess = serv->front_session; } } else { *action_type = MSGDEST_PRIVATE; sess = userquery; } } *is_highlight = is_hilight (from, text, sess, serv); if (sess != current_tab) { if (*from_me) { sess->msg_said = FALSE; sess->new_data = TRUE; } else { sess->msg_said = TRUE; sess->new_data = FALSE; } lastact_update (sess); } user = userlist_find (sess, from); if (user) { nickchar[0] = user->prefix[0]; user->lasttalk = time (0); if (user->account) *id = TRUE; if (user->me) *from_me = TRUE; } inbound_make_idtext (serv, idtext, sizeof (idtext), *id); *initial_session = sess; }
static void process_named_msg (session *sess, char *type, char *word[], char *word_eol[], const message_tags_data *tags_data) { server *serv = sess->server; char ip[128], nick[NICKLEN]; char *text, *ex; int len = strlen (type); /* fill in the "ip" and "nick" buffers */ ex = strchr (word[1], '!'); if (!ex) /* no '!', must be a server message */ { safe_strcpy (ip, word[1], sizeof (ip)); safe_strcpy (nick, word[1], sizeof (nick)); } else { safe_strcpy (ip, ex + 1, sizeof (ip)); ex[0] = 0; safe_strcpy (nick, word[1], sizeof (nick)); ex[0] = '!'; } if (len == 4) { guint32 t; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); /* this should compile to a bunch of: CMP.L, JE ... nice & fast */ switch (t) { case WORDL('J','O','I','N'): { char *chan = word[3]; char *account = word[4]; char *realname = word_eol[5]; if (account && strcmp (account, "*") == 0) account = NULL; if (realname && *realname == ':') realname++; if (*chan == ':') chan++; if (!serv->p_cmp (nick, serv->nick)) inbound_ujoin (serv, chan, nick, ip, tags_data); else inbound_join (serv, chan, nick, ip, account, realname, tags_data); } return; case WORDL('K','I','C','K'): { char *kicked = word[4]; char *reason = word_eol[5]; if (*kicked) { if (*reason == ':') reason++; if (!strcmp (kicked, serv->nick)) inbound_ukick (serv, word[3], nick, reason, tags_data); else inbound_kick (serv, word[3], kicked, nick, reason, tags_data); } } return; case WORDL('K','I','L','L'): { char *reason = word_eol[4]; if (*reason == ':') reason++; EMIT_SIGNAL_TIMESTAMP (XP_TE_KILL, sess, nick, reason, NULL, NULL, 0, tags_data->timestamp); } return; case WORDL('M','O','D','E'): handle_mode (serv, word, word_eol, nick, FALSE, tags_data); /* modes.c */ return; case WORDL('N','I','C','K'): inbound_newnick (serv, nick, (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3], FALSE, tags_data); return; case WORDL('P','A','R','T'): { char *chan = word[3]; char *reason = word_eol[4]; if (*chan == ':') chan++; if (*reason == ':') reason++; if (!strcmp (nick, serv->nick)) inbound_upart (serv, chan, ip, reason, tags_data); else inbound_part (serv, chan, nick, ip, reason, tags_data); } return; case WORDL('P','O','N','G'): inbound_ping_reply (serv->server_session, (word[4][0] == ':') ? word[4] + 1 : word[4], word[3], tags_data); return; case WORDL('Q','U','I','T'): inbound_quit (serv, nick, ip, (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3], tags_data); return; case WORDL('A','W','A','Y'): inbound_away_notify (serv, nick, (word_eol[3][0] == ':') ? word_eol[3] + 1 : NULL, tags_data); return; } goto garbage; } else if (len >= 5) { guint32 t; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); /* this should compile to a bunch of: CMP.L, JE ... nice & fast */ switch (t) { case WORDL('A','C','C','O'): inbound_account (serv, nick, word[3], tags_data); return; case WORDL('I','N','V','I'): if (ignore_check (word[1], IG_INVI)) return; if (word[4][0] == ':') EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, word[4] + 1, nick, serv->servername, NULL, 0, tags_data->timestamp); else EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, word[4], nick, serv->servername, NULL, 0, tags_data->timestamp); return; case WORDL('N','O','T','I'): { int id = FALSE; /* identified */ text = word_eol[4]; if (*text == ':') { text++; } #ifdef USE_OPENSSL if (!strncmp (text, "CHALLENGE ", 10)) /* QuakeNet CHALLENGE upon our request */ { char *response = challengeauth_response (((ircnet *)serv->network)->user ? ((ircnet *)serv->network)->user : prefs.hex_irc_user_name, serv->password, word[5]); tcp_sendf (serv, "PRIVMSG %s :CHALLENGEAUTH %s %s %s\r\n", CHALLENGEAUTH_NICK, ((ircnet *)serv->network)->user ? ((ircnet *)serv->network)->user : prefs.hex_irc_user_name, response, CHALLENGEAUTH_ALGO); g_free (response); return; /* omit the CHALLENGE <hash> ALGOS message */ } #endif if (serv->have_idmsg) { if (*text == '+') { id = TRUE; text++; } else if (*text == '-') text++; } if (!ignore_check (word[1], IG_NOTI)) inbound_notice (serv, word[3], nick, text, ip, id, tags_data); } return; case WORDL('P','R','I','V'): { char *to = word[3]; int len; int id = FALSE; /* identified */ if (*to) { /* Handle limited channel messages, for now no special event */ if (strchr (serv->chantypes, to[0]) == NULL && strchr (serv->nick_prefixes, to[0]) != NULL) to++; text = word_eol[4]; if (*text == ':') text++; if (serv->have_idmsg) { if (*text == '+') { id = TRUE; text++; } else if (*text == '-') text++; } len = strlen (text); if (text[0] == 1 && text[len - 1] == 1) /* ctcp */ { text[len - 1] = 0; text++; if (g_ascii_strncasecmp (text, "ACTION", 6) != 0) flood_check (nick, ip, serv, sess, 0); if (g_ascii_strncasecmp (text, "DCC ", 4) == 0) /* redo this with handle_quotes TRUE */ process_data_init (word[1], word_eol[1], word, word_eol, TRUE, FALSE); ctcp_handle (sess, to, nick, ip, text, word, word_eol, id, tags_data); } else { if (is_channel (serv, to)) { if (ignore_check (word[1], IG_CHAN)) return; inbound_chanmsg (serv, NULL, to, nick, text, FALSE, id, tags_data); } else { if (ignore_check (word[1], IG_PRIV)) return; inbound_privmsg (serv, nick, ip, text, id, tags_data); } } } } return; case WORDL('T','O','P','I'): inbound_topicnew (serv, nick, word[3], (word_eol[4][0] == ':') ? word_eol[4] + 1 : word_eol[4], tags_data); return; case WORDL('W','A','L','L'): text = word_eol[3]; if (*text == ':') text++; EMIT_SIGNAL_TIMESTAMP (XP_TE_WALLOPS, sess, nick, text, NULL, NULL, 0, tags_data->timestamp); return; } } else if (len == 3) { guint32 t; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); switch (t) { case WORDL('C','A','P','\0'): if (strncasecmp (word[4], "ACK", 3) == 0) { inbound_cap_ack (serv, word[1], word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5], tags_data); } else if (strncasecmp (word[4], "LS", 2) == 0) { inbound_cap_ls (serv, word[1], word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5], tags_data); } else if (strncasecmp (word[4], "NAK", 3) == 0) { inbound_cap_nak (serv, tags_data); } else if (strncasecmp (word[4], "LIST", 4) == 0) { inbound_cap_list (serv, word[1], word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5], tags_data); } return; } } garbage: /* unknown message */ PrintTextTimeStampf (sess, tags_data->timestamp, "GARBAGE: %s\n", word_eol[1]); }
void inbound_privmsg (server *serv, char *from, char *ip, char *text, int id) { session *sess; struct User *user; char idtext[64]; gboolean nodiag = FALSE; sess = find_dialog (serv, from); if (sess || prefs.hex_gui_autoopen_dialog) { /*0=ctcp 1=priv will set hex_gui_autoopen_dialog=0 here is flud detected */ if (!sess) { if (flood_check (from, ip, serv, current_sess, 1)) /* Create a dialog session */ sess = inbound_open_dialog (serv, from); else sess = serv->server_session; if (!sess) return; /* ?? */ } if (ip && ip[0]) { if (prefs.hex_irc_logging && sess->logfd != -1 && (!sess->topic || strcmp(sess->topic, ip))) { char tbuf[1024]; snprintf (tbuf, sizeof (tbuf), "[%s has address %s]\n", from, ip); write (sess->logfd, tbuf, strlen (tbuf)); } set_topic (sess, ip, ip); } inbound_chanmsg (serv, NULL, NULL, from, text, FALSE, id); return; } sess = find_session_from_nick (from, serv); if (!sess) { sess = serv->front_session; nodiag = TRUE; /* We don't want it to look like a normal message in front sess */ } user = userlist_find (sess, from); if (user) { user->lasttalk = time (0); if (user->account) id = TRUE; } inbound_make_idtext (serv, idtext, sizeof (idtext), id); if (sess->type == SESS_DIALOG && !nodiag) EMIT_SIGNAL (XP_TE_DPRIVMSG, sess, from, text, idtext, NULL, 0); else EMIT_SIGNAL (XP_TE_PRIVMSG, sess, from, text, idtext, NULL, 0); }
static void process_named_msg (session *sess, char *type, char *word[], char *word_eol[]) { server *serv = sess->server; char ip[128], nick[NICKLEN]; char *text, *ex; int len = strlen (type); /* fill in the "ip" and "nick" buffers */ ex = strchr (word[1], '!'); if (!ex) /* no '!', must be a server message */ { safe_strcpy (ip, word[1], sizeof (ip)); safe_strcpy (nick, word[1], sizeof (nick)); } else { safe_strcpy (ip, ex + 1, sizeof (ip)); ex[0] = 0; safe_strcpy (nick, word[1], sizeof (nick)); ex[0] = '!'; } if (len == 4) { guint32 t; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); /* this should compile to a bunch of: CMP.L, JE ... nice & fast */ switch (t) { case WORDL('J','O','I','N'): { char *chan = word[3]; if (*chan == ':') chan++; if (!serv->p_cmp (nick, serv->nick)) inbound_ujoin (serv, chan, nick, ip); else inbound_join (serv, chan, nick, ip); } return; case WORDL('K','I','C','K'): { char *kicked = word[4]; char *reason = word_eol[5]; if (*kicked) { if (*reason == ':') reason++; if (!strcmp (kicked, serv->nick)) inbound_ukick (serv, word[3], nick, reason); else inbound_kick (serv, word[3], kicked, nick, reason); } } return; case WORDL('K','I','L','L'): EMIT_SIGNAL (XP_TE_KILL, sess, nick, word_eol[5], NULL, NULL, 0); return; case WORDL('M','O','D','E'): handle_mode (serv, word, word_eol, nick, FALSE); /* modes.c */ return; case WORDL('N','I','C','K'): inbound_newnick (serv, nick, (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3], FALSE); return; case WORDL('P','A','R','T'): { char *chan = word[3]; char *reason = word_eol[4]; if (*chan == ':') chan++; if (*reason == ':') reason++; if (!strcmp (nick, serv->nick)) inbound_upart (serv, chan, ip, reason); else inbound_part (serv, chan, nick, ip, reason); } return; case WORDL('P','O','N','G'): inbound_ping_reply (serv->server_session, (word[4][0] == ':') ? word[4] + 1 : word[4], word[3]); return; case WORDL('Q','U','I','T'): inbound_quit (serv, nick, ip, (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3]); return; } goto garbage; } else if (len >= 5) { guint32 t; t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); /* this should compile to a bunch of: CMP.L, JE ... nice & fast */ switch (t) { case WORDL('I','N','V','I'): if (ignore_check (word[1], IG_INVI)) return; if (word[4][0] == ':') EMIT_SIGNAL (XP_TE_INVITED, sess, word[4] + 1, nick, serv->servername, NULL, 0); else EMIT_SIGNAL (XP_TE_INVITED, sess, word[4], nick, serv->servername, NULL, 0); return; case WORDL('N','O','T','I'): { int id = FALSE; /* identified */ text = word_eol[4]; if (*text == ':') text++; if (serv->have_idmsg) { if (*text == '+') { id = TRUE; text++; } else if (*text == '-') text++; } if (!ignore_check (word[1], IG_NOTI)) inbound_notice (serv, word[3], nick, text, ip, id); } return; case WORDL('P','R','I','V'): { char *to = word[3]; int len; int id = FALSE; /* identified */ if (*to) { text = word_eol[4]; if (*text == ':') text++; if (serv->have_idmsg) { if (*text == '+') { id = TRUE; text++; } else if (*text == '-') text++; } len = strlen (text); if (text[0] == 1 && text[len - 1] == 1) /* ctcp */ { text[len - 1] = 0; text++; if (g_ascii_strncasecmp (text, "ACTION", 6) != 0) flood_check (nick, ip, serv, sess, 0); if (g_ascii_strncasecmp (text, "DCC ", 4) == 0) /* redo this with handle_quotes TRUE */ process_data_init (word[1], word_eol[1], word, word_eol, TRUE, FALSE); ctcp_handle (sess, to, nick, ip, text, word, word_eol, id); } else { if (is_channel (serv, to)) { if (ignore_check (word[1], IG_CHAN)) return; inbound_chanmsg (serv, NULL, to, nick, text, FALSE, id); } else { if (ignore_check (word[1], IG_PRIV)) return; inbound_privmsg (serv, nick, ip, text, id); } } } } return; case WORDL('T','O','P','I'): inbound_topicnew (serv, nick, word[3], (word_eol[4][0] == ':') ? word_eol[4] + 1 : word_eol[4]); return; case WORDL('W','A','L','L'): text = word_eol[3]; if (*text == ':') text++; EMIT_SIGNAL (XP_TE_WALLOPS, sess, nick, text, NULL, NULL, 0); return; } } else if (len == 3) { guint32 t; guint32 want_cap; /* format the CAP REQ string based on previous capabilities being requested or not */ guint32 want_sasl; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */ char *pass; /* buffer for SASL password */ char buffer[256]; /* buffer for requesting capabilities and emitting the signal */ t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); switch (t) { case WORDL('C','A','P','\0'): if (strncasecmp (word[4], "ACK", 3) == 0) { EMIT_SIGNAL (XP_TE_CAPACK, sess->server->server_session, word[1], word[5][0]==':' ? ++word_eol[5] : word_eol[5], NULL, NULL, 0); if (strstr (word_eol[5], "identify-msg") != 0) { serv->have_idmsg = TRUE; } if (strstr (word_eol[5], "multi-prefix") != 0) { serv->have_namesx = TRUE; } if (strstr (word_eol[5], "sasl") != 0) { serv->have_sasl = TRUE; EMIT_SIGNAL (XP_TE_SASLAUTH, serv->server_session, sess->server->sasluser, NULL, NULL, NULL, 0); tcp_send_len (serv, "AUTHENTICATE PLAIN\r\n", 20); pass = encode_sasl_pass (sess->server->sasluser, sess->server->saslpassword); tcp_sendf (sess->server, "AUTHENTICATE %s\r\n", pass); free (pass); } } else if (strncasecmp (word[4], "LS", 2) == 0) { EMIT_SIGNAL (XP_TE_CAPLIST, serv->server_session, word[1], word[5][0]==':' ? ++word_eol[5] : word_eol[5], NULL, NULL, 0); want_cap = 0; want_sasl = 0; if (strstr (word_eol[5], "identify-msg") != 0) { strcpy (buffer, "CAP REQ :identify-msg"); want_cap = 1; } if (strstr (word_eol[5], "multi-prefix") != 0) { want_cap ? strcat (buffer, " multi-prefix") : strcpy (buffer, "CAP REQ :multi-prefix"); want_cap = 1; } /* if the SASL password is set, request SASL auth */ if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->saslpassword) != 0) { want_cap ? strcat (buffer, " sasl") : strcpy (buffer, "CAP REQ :sasl"); want_sasl = 1; } if (want_cap) { /* buffer + 9 = emit buffer without "CAP REQ :" */ EMIT_SIGNAL (XP_TE_CAPREQ, sess->server->server_session, buffer + 9, NULL, NULL, NULL, 0); tcp_sendf (serv, "%s\r\n", buffer); } if (!want_sasl) { /* if we use SASL, CAP END is dealt via raw numerics */ tcp_send_len (serv, "CAP END\r\n", 9); } } else if (strncasecmp (word[4], "NAK", 3) == 0) { tcp_send_len (serv, "CAP END\r\n", 9); } return; } } garbage: /* unknown message */ PrintTextf (sess, "GARBAGE: %s\n", word_eol[1]); }