static session * inbound_open_dialog (server * serv, char *from) { session *sess; sess = new_ircwindow (serv, from, SESS_DIALOG, 0); /* for playing sounds */ EMIT_SIGNAL (XP_TE_OPENDIALOG, sess, NULL, NULL, NULL, NULL, 0); return sess; }
void inbound_ping_reply (session * sess, char *timestring, char *from) { unsigned long tim, nowtim, dif; int lag = 0; char outbuf[64]; if (strncmp (timestring, "LAG", 3) == 0) { timestring += 3; lag = 1; } tim = strtoul (timestring, NULL, 10); nowtim = make_ping_time (); dif = nowtim - tim; sess->server->ping_recv = time (0); if (lag) { sess->server->lag_sent = 0; sess->server->lag = dif / 1000; fe_set_lag (sess->server, dif / 100000); return; } if (atol (timestring) == 0) { if (sess->server->lag_sent) sess->server->lag_sent = 0; else EMIT_SIGNAL (XP_TE_PINGREP, sess, from, "?", NULL, NULL, 0); } else { snprintf (outbuf, sizeof (outbuf), "%ld.%ld%ld", dif / 1000000, (dif / 100000) % 10, dif % 10); EMIT_SIGNAL (XP_TE_PINGREP, sess, from, outbuf, NULL, NULL, 0); } }
void inbound_next_nick (session *sess, char *nick) { sess->server->nickcount++; switch (sess->server->nickcount) { case 2: sess->server->p_change_nick (sess->server, prefs.nick2); EMIT_SIGNAL (XP_TE_NICKCLASH, sess, nick, prefs.nick2, NULL, NULL, 0); break; case 3: sess->server->p_change_nick (sess->server, prefs.nick3); EMIT_SIGNAL (XP_TE_NICKCLASH, sess, nick, prefs.nick3, NULL, NULL, 0); break; default: EMIT_SIGNAL (XP_TE_NICKFAIL, sess, NULL, NULL, NULL, NULL, 0); } }
void inbound_topictime (server *serv, char *chan, char *nick, time_t stamp) { char *tim = ctime (&stamp); session *sess = find_channel (serv, chan); if (!sess) sess = serv->server_session; tim[24] = 0; /* get rid of the \n */ EMIT_SIGNAL (XP_TE_TOPICDATE, sess, chan, nick, tim, NULL, 0); }
void inbound_sasl_authenticate (server *serv, char *data) { ircnet *net = (ircnet*)serv->network; char *user, *pass = NULL; const char *mech = sasl_mechanisms[serv->sasl_mech]; /* Got a list of supported mechanisms from inspircd */ if (strchr (data, ',') != NULL) { inbound_sasl_supportedmechs (serv, data); return; } if (net->user && !(net->flags & FLAG_USE_GLOBAL)) user = net->user; else user = prefs.hex_irc_user_name; switch (serv->sasl_mech) { case MECH_PLAIN: pass = encode_sasl_pass_plain (user, serv->password); break; #ifdef USE_OPENSSL case MECH_BLOWFISH: pass = encode_sasl_pass_blowfish (user, serv->password, data); break; case MECH_AES: pass = encode_sasl_pass_aes (user, serv->password, data); break; case MECH_EXTERNAL: pass = g_strdup ("+"); break; #endif } if (pass == NULL) { /* something went wrong abort */ serv->sent_saslauth = TRUE; /* prevent trying PLAIN */ tcp_sendf (serv, "AUTHENTICATE *\r\n"); return; } serv->sent_saslauth = TRUE; tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass); g_free (pass); EMIT_SIGNAL (XP_TE_SASLAUTH, serv->server_session, user, (char*)mech); }
void do_dns (session *sess, char *nick, char *host) { char *po; char tbuf[1024]; po = strrchr (host, '@'); if (po) host = po + 1; EMIT_SIGNAL (XP_TE_RESOLVINGUSER, sess, nick, host, NULL, NULL, 0); snprintf (tbuf, sizeof (tbuf), "exec -d %s %s", prefs.hex_dnsprogram, host); handle_command (sess, tbuf, FALSE); }
void inbound_foundip (session *sess, char *ip) { struct hostent *HostAddr; HostAddr = gethostbyname (ip); if (HostAddr) { prefs.dcc_ip = ((struct in_addr *) HostAddr->h_addr)->s_addr; EMIT_SIGNAL (XP_TE_FOUNDIP, sess, inet_ntoa (*((struct in_addr *) HostAddr->h_addr)), NULL, NULL, NULL, 0); } }
void inbound_topic (server * serv, char *chan, char *topic_text) { session *sess = find_channel (serv, chan); if (sess) { set_topic (sess, topic_text, topic_text); } else sess = serv->server_session; EMIT_SIGNAL (XP_TE_TOPIC, sess, chan, topic_text, NULL, NULL, 0); }
void inbound_ujoin (server *serv, char *chan, char *nick, char *ip) { session *sess; /* already joined? probably a bnc */ sess = find_channel (serv, chan); if (!sess) { /* see if a window is waiting to join this channel */ sess = find_session_from_waitchannel (chan, serv); if (!sess) { /* find a "<none>" tab and use that */ sess = find_unused_session (serv); if (!sess) /* last resort, open a new tab/window */ sess = new_ircwindow (serv, chan, SESS_CHANNEL); } } safe_strcpy (sess->channel, chan, CHANLEN); fe_set_channel (sess); fe_set_title (sess); fe_set_nonchannel (sess, TRUE); clear_user_list (sess); if (prefs.logging) log_open (sess); sess->waitchannel[0] = 0; sess->ignore_date = TRUE; sess->ignore_mode = TRUE; sess->ignore_names = TRUE; sess->end_of_names = FALSE; /* sends a MODE */ serv->p_join_info (sess->server, chan); EMIT_SIGNAL (XP_TE_UJOIN, sess, nick, chan, ip, NULL, 0); if (prefs.userhost) { /* sends WHO #channel */ serv->p_user_list (sess->server, chan); sess->doing_who = TRUE; } }
void inbound_ukick (server *serv, char *chan, char *kicker, char *reason) { session *sess = find_channel (serv, chan); if (sess) { EMIT_SIGNAL (XP_TE_UKICK, sess, serv->nick, chan, kicker, reason, 0); clear_channel (sess); if (prefs.hex_irc_auto_rejoin) { serv->p_join (serv, chan, sess->channelkey); safe_strcpy (sess->waitchannel, chan, CHANLEN); } } }
void inbound_topicnew (server *serv, char *nick, char *chan, char *topic) { session *sess; char *stripped_topic; sess = find_channel (serv, chan); if (sess) { EMIT_SIGNAL (XP_TE_NEWTOPIC, sess, nick, topic, chan, NULL, 0); stripped_topic = strip_color (topic, -1, STRIP_ALL); set_topic (sess, topic, stripped_topic); g_free (stripped_topic); } }
void inbound_away_notify (server *serv, char *nick, char *reason) { session *sess = NULL; GSList *list; list = sess_list; while (list) { sess = list->data; if (sess->server == serv) { userlist_set_away (sess, nick, reason ? TRUE : FALSE); if (sess == serv->front_session && notify_is_in_list (serv, nick)) { if (reason) EMIT_SIGNAL (XP_TE_NOTIFYAWAY, sess, nick, reason, NULL, NULL, 0); else EMIT_SIGNAL (XP_TE_NOTIFYBACK, sess, nick, NULL, NULL, NULL, 0); } } list = list->next; } }
void inbound_topicnew (server *serv, char *nick, char *chan, char *topic) { session *sess; char *new_topic; sess = find_channel (serv, chan); if (sess) { new_topic = strip_color (topic); set_topic (sess, new_topic); free (new_topic); EMIT_SIGNAL (XP_TE_NEWTOPIC, sess, nick, topic, chan, NULL, 0); } }
void inbound_topic (server *serv, char *chan, char *topic_text) { session *sess = find_channel (serv, chan); char *new_topic; if (sess) { new_topic = strip_color (topic_text); set_topic (sess, new_topic); free (new_topic); } else sess = serv->server_session; EMIT_SIGNAL (XP_TE_TOPIC, sess, chan, topic_text, NULL, NULL, 0); }
static void notify_announce_offline (server * serv, struct notify_per_server *servnot, char *nick, int quiet) { session *sess; sess = serv->front_session; servnot->ison = FALSE; servnot->lastoff = time (0); if (!quiet) EMIT_SIGNAL (XP_TE_NOTIFYOFFLINE, sess, nick, serv->servername, server_get_network (serv, TRUE), NULL, 0); fe_notify_update (nick); fe_notify_update (0); }
void inbound_topic (server *serv, char *chan, char *topic_text) { session *sess = find_channel (serv, chan); char *stripped_topic; if (sess) { stripped_topic = strip_color (topic_text, -1, STRIP_ALL); set_topic (sess, topic_text, stripped_topic); g_free (stripped_topic); } else sess = serv->server_session; EMIT_SIGNAL (XP_TE_TOPIC, sess, chan, topic_text, NULL, NULL, 0); }
void inbound_topic (server * serv, char *chan, char *topic_text) { session *sess = find_channel (serv, chan); if (sess) { if (!prefs.topic_color) set_topic(sess, topic_text, strip_color(topic_text, -1, STRIP_ALL)); else set_topic(sess, topic_text, topic_text); } else sess = serv->server_session; EMIT_SIGNAL (XP_TE_TOPIC, sess, chan, topic_text, NULL, NULL, 0); }
void inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, char *banner) { char *time_str = ctime (&stamp); server *serv = sess->server; time_str[19] = 0; /* get rid of the \n */ if (stamp == 0) time_str = ""; sess = find_channel (serv, chan); if (!sess) sess = serv->front_session; if (!fe_is_banwindow (sess)) EMIT_SIGNAL (XP_TE_BANLIST, sess, chan, mask, banner, time_str, 0); else fe_add_ban_list (sess, mask, banner, time_str); }
void lag_check (void) { server *serv; GSList *list = serv_list; unsigned long tim; char tbuf[128]; time_t now = time (0); time_t lag; tim = make_ping_time (); while (list) { serv = list->data; if (serv->connected && serv->end_of_motd) { lag = now - serv->ping_recv; if (prefs.hex_net_ping_timeout != 0 && lag > prefs.hex_net_ping_timeout && lag > 0) { sprintf (tbuf, "%" G_GINT64_FORMAT, (gint64) lag); EMIT_SIGNAL (XP_TE_PINGTIMEOUT, serv->server_session, tbuf, NULL, NULL, NULL, 0); if (prefs.hex_net_auto_reconnect) serv->auto_reconnect (serv, FALSE, -1); } else { g_snprintf (tbuf, sizeof (tbuf), "LAG%lu", tim); serv->p_ping (serv, "", tbuf); if (!serv->lag_sent) { serv->lag_sent = tim; fe_set_lag (serv, -1); } } } list = list->next; } }
static void dcc_abort (struct DCC *dcc) { if (dcc) { switch (dcc->dccstat) { case STAT_QUEUED: case STAT_CONNECTING: case STAT_ACTIVE: dcc_close (dcc, STAT_ABORTED, FALSE); EMIT_SIGNAL (XP_TE_DCCABORT, dcc->serv->front_session, dcctypes[(int) dcc->type], file_part (dcc->file), dcc->nick, NULL, 0); break; default: dcc_close (dcc, 0, TRUE); } } }
void inbound_away (server * serv, char *nick, char *msg) { struct away_msg *away = server_away_find_message (serv, nick); session *sess = NULL; GSList *list; if (away && !strcmp (msg, away->message)) /* Seen the msg before? */ { if (prefs.show_away_once && !serv->inside_whois) return; } else { server_away_save_message (serv, nick, msg); } if (prefs.irc_whois_front) sess = serv->front_session; else { if (!serv->inside_whois) sess = find_session_from_nick (nick, serv); if (!sess) sess = serv->server_session; } /* possibly hide the output */ if (!serv->inside_whois || !serv->skip_next_whois) EMIT_SIGNAL (XP_TE_WHOIS5, sess, nick, msg, NULL, NULL, 0); list = sess_list; while (list) { sess = list->data; if (sess->server == serv) userlist_set_away (sess, nick, TRUE); list = list->next; } }
void inbound_notice (server *serv, char *to, char *nick, char *msg, char *ip, int id) { char *po,*ptr=to; session *sess = 0; int server_notice = FALSE; if (is_channel (serv, ptr)) sess = find_channel (serv, ptr); if (!sess && ptr[0] == '@') { ptr++; sess = find_channel (serv, ptr); } if (!sess && ptr[0] == '%') { ptr++; sess = find_channel (serv, ptr); } if (!sess && ptr[0] == '+') { ptr++; sess = find_channel (serv, ptr); } if (strcmp (nick, ip) == 0) server_notice = TRUE; if (!sess) { ptr = 0; if (prefs.hex_gui_tab_notices) { int stype = server_notice ? SESS_SNOTICES : SESS_NOTICES; sess = find_session_from_type (stype, serv); if (!sess) { if (stype == SESS_NOTICES) sess = new_ircwindow (serv, "(notices)", SESS_NOTICES, 0); else sess = new_ircwindow (serv, "(snotices)", SESS_SNOTICES, 0); fe_set_channel (sess); fe_set_title (sess); fe_set_nonchannel (sess, FALSE); userlist_clear (sess); log_open_or_close (sess); } /* Avoid redundancy with some Undernet notices */ if (!strncmp (msg, "*** Notice -- ", 14)) msg += 14; } else { /* paranoia check */ if (msg[0] == '[' && (!serv->have_idmsg || id)) { /* guess where chanserv meant to post this -sigh- */ if (!g_ascii_strcasecmp (nick, "ChanServ") && !find_dialog (serv, nick)) { char *dest = strdup (msg + 1); char *end = strchr (dest, ']'); if (end) { *end = 0; sess = find_channel (serv, dest); } free (dest); } } if (!sess) sess = find_session_from_nick (nick, serv); } if (!sess) { if (server_notice) sess = serv->server_session; else sess = serv->front_session; } } if (msg[0] == 1) { msg++; if (!strncmp (msg, "PING", 4)) { inbound_ping_reply (sess, msg + 5, nick); return; } } po = strchr (msg, '\001'); if (po) po[0] = 0; if (server_notice) EMIT_SIGNAL (XP_TE_SERVNOTICE, sess, msg, nick, NULL, NULL, 0); else if (ptr) EMIT_SIGNAL (XP_TE_CHANNOTICE, sess, nick, to, msg, NULL, 0); else EMIT_SIGNAL (XP_TE_NOTICE, sess, nick, msg, NULL, NULL, 0); }
void inbound_notice (server * serv, char *to, char *nick, char *msg, char *ip, int id) { char *po, *ptr = to; session *sess = 0; int server_notice = FALSE; if (is_channel (serv, ptr)) sess = find_channel (serv, ptr); if (!sess && ptr[0] == '@') { ptr++; sess = find_channel (serv, ptr); } if (!sess && ptr[0] == '%') { ptr++; sess = find_channel (serv, ptr); } if (!sess && ptr[0] == '+') { ptr++; sess = find_channel (serv, ptr); } if (strcmp (nick, ip) == 0) server_notice = TRUE; if (!sess) { ptr = 0; /* paranoia check */ if (msg[0] == '[' && (!serv->have_idmsg || id)) { /* guess where a services bot meant to put this */ if (!find_dialog (serv, nick)) { char *dest = strdup (msg + 1); char *end = strchr (dest, ']'); if (end) { *end = 0; sess = find_channel (serv, dest); } free (dest); } } if (!sess) { if (server_notice) sess = serv->server_session; else sess = serv->front_session; } } if (msg[0] == 1) { msg++; if (!strncmp (msg, "PING", 4)) { inbound_ping_reply (sess, msg + 5, nick); return; } } po = strchr (msg, '\001'); if (po) po[0] = 0; if (server_notice) EMIT_SIGNAL (XP_TE_SERVNOTICE, sess, msg, nick, NULL, NULL, 0); else if (ptr) EMIT_SIGNAL (XP_TE_CHANNOTICE, sess, nick, to, msg, NULL, 0); else EMIT_SIGNAL (XP_TE_NOTICE, sess, nick, msg, NULL, NULL, 0); }
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 handle_single_mode (mode_run *mr, char sign, char mode, char *nick, char *chan, char *arg, int quiet, int is_324) { session *sess; server *serv = mr->serv; char outbuf[4]; char *cm = serv->chanmodes; gboolean supportsq = FALSE; outbuf[0] = sign; outbuf[1] = 0; outbuf[2] = mode; outbuf[3] = 0; sess = find_channel (serv, chan); if (!sess || !is_channel (serv, chan)) { /* got modes for a chan we're not in! probably nickmode +isw etc */ sess = serv->front_session; goto genmode; } /* is this a nick mode? */ if (strchr (serv->nick_modes, mode)) { /* update the user in the userlist */ userlist_update_mode (sess, /*nickname */ arg, mode, sign); } else { if (!is_324 && !sess->ignore_mode && mode_chanmode_type(serv, mode) >= 1) record_chan_mode (sess, sign, mode, arg); } /* Is q a chanmode on this server? */ if (cm) while (*cm) { if (*cm == ',') break; if (*cm == 'q') supportsq = TRUE; cm++; } switch (sign) { case '+': switch (mode) { case 'k': safe_strcpy (sess->channelkey, arg, sizeof (sess->channelkey)); fe_update_channel_key (sess); fe_update_mode_buttons (sess, mode, sign); if (!quiet) EMIT_SIGNAL (XP_TE_CHANSETKEY, sess, nick, arg, NULL, NULL, 0); return; case 'l': sess->limit = atoi (arg); fe_update_channel_limit (sess); fe_update_mode_buttons (sess, mode, sign); if (!quiet) EMIT_SIGNAL (XP_TE_CHANSETLIMIT, sess, nick, arg, NULL, NULL, 0); return; case 'o': if (!quiet) mr->op = mode_cat (mr->op, arg); return; case 'h': if (!quiet) EMIT_SIGNAL (XP_TE_CHANHOP, sess, nick, arg, NULL, NULL, 0); return; case 'v': if (!quiet) mr->voice = mode_cat (mr->voice, arg); return; case 'b': if (!quiet) EMIT_SIGNAL (XP_TE_CHANBAN, sess, nick, arg, NULL, NULL, 0); return; case 'e': if (!quiet) EMIT_SIGNAL (XP_TE_CHANEXEMPT, sess, nick, arg, NULL, NULL, 0); return; case 'I': if (!quiet) EMIT_SIGNAL (XP_TE_CHANINVITE, sess, nick, arg, NULL, NULL, 0); return; case 'q': if (!supportsq) break; /* +q is owner on this server */ if (!quiet) EMIT_SIGNAL (XP_TE_CHANQUIET, sess, nick, arg, NULL, NULL, 0); return; } break; case '-': switch (mode) { case 'k': sess->channelkey[0] = 0; fe_update_channel_key (sess); fe_update_mode_buttons (sess, mode, sign); if (!quiet) EMIT_SIGNAL (XP_TE_CHANRMKEY, sess, nick, NULL, NULL, NULL, 0); return; case 'l': sess->limit = 0; fe_update_channel_limit (sess); fe_update_mode_buttons (sess, mode, sign); if (!quiet) EMIT_SIGNAL (XP_TE_CHANRMLIMIT, sess, nick, NULL, NULL, NULL, 0); return; case 'o': if (!quiet) mr->deop = mode_cat (mr->deop, arg); return; case 'h': if (!quiet) EMIT_SIGNAL (XP_TE_CHANDEHOP, sess, nick, arg, NULL, NULL, 0); return; case 'v': if (!quiet) mr->devoice = mode_cat (mr->devoice, arg); return; case 'b': if (!quiet) EMIT_SIGNAL (XP_TE_CHANUNBAN, sess, nick, arg, NULL, NULL, 0); return; case 'e': if (!quiet) EMIT_SIGNAL (XP_TE_CHANRMEXEMPT, sess, nick, arg, NULL, NULL, 0); return; case 'I': if (!quiet) EMIT_SIGNAL (XP_TE_CHANRMINVITE, sess, nick, arg, NULL, NULL, 0); return; case 'q': if (!supportsq) break; /* -q is owner on this server */ if (!quiet) EMIT_SIGNAL (XP_TE_CHANUNQUIET, sess, nick, arg, NULL, NULL, 0); return; } } fe_update_mode_buttons (sess, mode, sign); genmode: /* Received umode +e. If we're waiting to send JOIN then send now! */ if (mode == 'e' && sign == '+' && !serv->p_cmp (chan, serv->nick)) inbound_identified (serv); if (!quiet) { if (*arg) { char *buf = malloc (strlen (chan) + strlen (arg) + 2); sprintf (buf, "%s %s", chan, arg); EMIT_SIGNAL (XP_TE_CHANMODEGEN, sess, nick, outbuf, outbuf + 2, buf, 0); free (buf); } else EMIT_SIGNAL (XP_TE_CHANMODEGEN, sess, nick, outbuf, outbuf + 2, chan, 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 process_numeric (session * sess, int n, char *word[], char *word_eol[], char *text) { server *serv = sess->server; /* show whois is the server tab */ session *whois_sess = serv->server_session; /* unless this setting is on */ if (prefs.irc_whois_front) whois_sess = serv->front_session; switch (n) { case 1: inbound_login_start (sess, word[3], word[1]); /* if network is PTnet then you must get your IP address from "001" server message */ if ((strncmp(word[7], "PTnet", 5) == 0) && (strncmp(word[8], "IRC", 3) == 0) && (strncmp(word[9], "Network", 7) == 0) && (strrchr(word[10], '@') != NULL)) { serv->use_who = FALSE; if (prefs.ip_from_server) inbound_foundip (sess, strrchr(word[10], '@')+1); } /* use /NICKSERV */ if (strcasecmp (word[7], "DALnet") == 0 || strcasecmp (word[7], "BRASnet") == 0) serv->nickservtype = 1; /* use /NS */ else if (strcasecmp (word[7], "FreeNode") == 0) serv->nickservtype = 2; goto def; case 4: /* check the ircd type */ serv->use_listargs = FALSE; serv->modes_per_line = 3; /* default to IRC RFC */ if (strncmp (word[5], "bahamut", 7) == 0) /* DALNet */ { serv->use_listargs = TRUE; /* use the /list args */ } else if (strncmp (word[5], "u2.10.", 6) == 0) /* Undernet */ { serv->use_listargs = TRUE; /* use the /list args */ serv->modes_per_line = 6; /* allow 6 modes per line */ } else if (strncmp (word[5], "glx2", 4) == 0) { serv->use_listargs = TRUE; /* use the /list args */ } goto def; case 5: inbound_005 (serv, word); goto def; case 263: /*Server load is temporarily too heavy */ if (fe_is_chanwindow (sess->server)) { fe_chan_list_end (sess->server); fe_message (word_eol[5] + 1, FE_MSG_ERROR); } goto def; case 290: /* CAPAB reply */ if (strstr (word_eol[1], "IDENTIFY-MSG")) { serv->have_idmsg = TRUE; break; } goto def; case 301: inbound_away (serv, word[4], (word_eol[5][0] == ':') ? word_eol[5] + 1 : word_eol[5]); break; case 302: if (serv->skip_next_userhost) { char *eq = strchr (word[4], '='); if (eq) { *eq = 0; if (!serv->p_cmp (word[4] + 1, serv->nick)) { char *at = strrchr (eq + 1, '@'); if (at) inbound_foundip (sess, at + 1); } } serv->skip_next_userhost = FALSE; break; } else goto def; case 303: word[4]++; notify_markonline (serv, word); break; case 305: inbound_uback (serv); goto def; case 306: inbound_uaway (serv); goto def; case 312: if (!serv->skip_next_whois) EMIT_SIGNAL (XP_TE_WHOIS3, whois_sess, word[4], word_eol[5], NULL, NULL, 0); else inbound_user_info (sess, NULL, NULL, NULL, word[5], word[4], NULL, 0xff); break; case 311: /* WHOIS 1st line */ serv->inside_whois = 1; inbound_user_info_start (sess, word[4]); if (!serv->skip_next_whois) EMIT_SIGNAL (XP_TE_WHOIS1, whois_sess, word[4], word[5], word[6], word_eol[8] + 1, 0); else inbound_user_info (sess, NULL, word[5], word[6], NULL, word[4], word_eol[8][0] == ':' ? word_eol[8] + 1 : word_eol[8], 0xff); break; case 314: /* WHOWAS */ inbound_user_info_start (sess, word[4]); EMIT_SIGNAL (XP_TE_WHOIS1, whois_sess, word[4], word[5], word[6], word_eol[8] + 1, 0); break; case 317: if (!serv->skip_next_whois) { time_t timestamp = (time_t) atol (word[6]); long idle = atol (word[5]); char *tim; char outbuf[64]; snprintf (outbuf, sizeof (outbuf), "%02ld:%02ld:%02ld", idle / 3600, (idle / 60) % 60, idle % 60); if (timestamp == 0) EMIT_SIGNAL (XP_TE_WHOIS4, whois_sess, word[4], outbuf, NULL, NULL, 0); else { tim = ctime (×tamp); tim[19] = 0; /* get rid of the \n */ EMIT_SIGNAL (XP_TE_WHOIS4T, whois_sess, word[4], outbuf, tim, NULL, 0); } } break; case 318: /* END OF WHOIS */ if (!serv->skip_next_whois) EMIT_SIGNAL (XP_TE_WHOIS6, whois_sess, word[4], NULL, NULL, NULL, 0); serv->skip_next_whois = 0; serv->inside_whois = 0; break; case 313: case 319: if (!serv->skip_next_whois) EMIT_SIGNAL (XP_TE_WHOIS2, whois_sess, word[4], word_eol[5] + 1, NULL, NULL, 0); break; case 307: /* dalnet version */ case 320: /* :is an identified user */ if (!serv->skip_next_whois) EMIT_SIGNAL (XP_TE_WHOIS_ID, whois_sess, word[4], word_eol[5] + 1, NULL, NULL, 0); break; case 321: if (!fe_is_chanwindow (sess->server)) EMIT_SIGNAL (XP_TE_CHANLISTHEAD, serv->server_session, NULL, NULL, NULL, NULL, 0); break; case 322: if (fe_is_chanwindow (sess->server)) { fe_add_chan_list (sess->server, word[4], word[5], word_eol[6] + 1); } else { PrintTextf (serv->server_session, "%-16s %-7d %s\017\n", word[4], atoi (word[5]), word_eol[6] + 1); } break; case 323: if (!fe_is_chanwindow (sess->server)) EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, text, word[1], word[2], NULL, 0); else fe_chan_list_end (sess->server); break; case 324: sess = find_channel (serv, word[4]); if (!sess) sess = serv->server_session; if (sess->ignore_mode) sess->ignore_mode = FALSE; else EMIT_SIGNAL (XP_TE_CHANMODES, sess, word[4], word_eol[5], NULL, NULL, 0); fe_update_mode_buttons (sess, 't', '-'); fe_update_mode_buttons (sess, 'n', '-'); fe_update_mode_buttons (sess, 's', '-'); fe_update_mode_buttons (sess, 'i', '-'); fe_update_mode_buttons (sess, 'p', '-'); fe_update_mode_buttons (sess, 'm', '-'); fe_update_mode_buttons (sess, 'l', '-'); fe_update_mode_buttons (sess, 'k', '-'); handle_mode (serv, word, word_eol, "", TRUE); break; case 329: sess = find_channel (serv, word[4]); if (sess) { if (sess->ignore_date) sess->ignore_date = FALSE; else channel_date (sess, word[4], word[5]); } break; case 330: if (!serv->skip_next_whois) EMIT_SIGNAL (XP_TE_WHOIS_AUTH, whois_sess, word[4], word_eol[6] + 1, word[5], NULL, 0); break; case 332: inbound_topic (serv, word[4], (word_eol[5][0] == ':') ? word_eol[5] + 1 : word_eol[5]); break; case 333: inbound_topictime (serv, word[4], word[5], atol (word[6])); break; #if 0 case 338: /* Undernet Real user@host, Real IP */ EMIT_SIGNAL (XP_TE_WHOIS_REALHOST, sess, word[4], word[5], word[6], (word_eol[7][0]==':') ? word_eol[7]+1 : word_eol[7], 0); break; #endif case 341: /* INVITE ACK */ EMIT_SIGNAL (XP_TE_UINVITE, sess, word[4], word[5], serv->servername, NULL, 0); break; case 352: /* WHO */ { unsigned int away = 0; session *who_sess = find_channel (serv, word[4]); if (*word[9] == 'G') away = 1; inbound_user_info (sess, word[4], word[5], word[6], word[7], word[8], word_eol[11], away); /* try to show only user initiated whos */ if (!who_sess || !who_sess->doing_who) EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, text, word[1], word[2], NULL, 0); } break; case 354: /* undernet WHOX: used as a reply for irc_away_status */ { unsigned int away = 0; session *who_sess; /* irc_away_status sends out a "152" */ if (!strcmp (word[4], "152")) { who_sess = find_channel (serv, word[5]); if (*word[7] == 'G') away = 1; /* :SanJose.CA.us.undernet.org 354 z1 152 #zed1 z1 H@ */ inbound_user_info (sess, word[5], 0, 0, 0, word[6], 0, away); /* try to show only user initiated whos */ if (!who_sess || !who_sess->doing_who) EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, text, word[1], word[2], NULL, 0); } else goto def; } break; case 315: /* END OF WHO */ { session *who_sess; who_sess = find_channel (serv, word[4]); if (who_sess) { if (!who_sess->doing_who) EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, text, word[1], word[2], NULL, 0); who_sess->doing_who = FALSE; } else { if (!serv->doing_dns) EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, text, word[1], word[2], NULL, 0); serv->doing_dns = FALSE; } } break; case 348: /* +e-list entry */ if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], TRUE)) goto def; break; case 349: /* end of exemption list */ sess = find_channel (serv, word[4]); if (!sess) { sess = serv->front_session; goto def; } if (!fe_is_banwindow (sess)) goto def; fe_ban_list_end (sess, TRUE); break; case 353: /* NAMES */ inbound_nameslist (serv, word[5], (word_eol[6][0] == ':') ? word_eol[6] + 1 : word_eol[6]); break; case 366: if (!inbound_nameslist_end (serv, word[4])) goto def; break; case 367: /* banlist entry */ inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], FALSE); break; case 368: sess = find_channel (serv, word[4]); if (!sess) { sess = serv->front_session; goto def; } if (!fe_is_banwindow (sess)) goto def; fe_ban_list_end (sess, FALSE); break; case 369: /* WHOWAS end */ case 406: /* WHOWAS error */ EMIT_SIGNAL (XP_TE_SERVTEXT, whois_sess, text, word[1], word[2], NULL, 0); serv->inside_whois = 0; break; case 372: /* motd text */ case 375: /* motd start */ if (!prefs.skipmotd || serv->motd_skipped) EMIT_SIGNAL (XP_TE_MOTD, serv->server_session, text, NULL, NULL, NULL, 0); break; case 376: /* end of motd */ case 422: /* motd file is missing */ inbound_login_end (sess, text); break; case 433: /* nickname in use */ case 432: /* erroneous nickname */ if (serv->end_of_motd) goto def; inbound_next_nick (sess, word[4]); break; case 437: if (serv->end_of_motd || is_channel (serv, word[4])) goto def; inbound_next_nick (sess, word[4]); break; case 471: EMIT_SIGNAL (XP_TE_USERLIMIT, sess, word[4], NULL, NULL, NULL, 0); break; case 473: EMIT_SIGNAL (XP_TE_INVITE, sess, word[4], NULL, NULL, NULL, 0); break; case 474: EMIT_SIGNAL (XP_TE_BANNED, sess, word[4], NULL, NULL, NULL, 0); break; case 475: EMIT_SIGNAL (XP_TE_KEYWORD, sess, word[4], NULL, NULL, NULL, 0); break; case 601: notify_set_offline (serv, word[4], FALSE); break; case 605: notify_set_offline (serv, word[4], TRUE); break; case 600: case 604: notify_set_online (serv, word[4]); break; default: if (serv->inside_whois && word[4][0]) { /* some unknown WHOIS reply, ircd coders make them up weekly */ if (!serv->skip_next_whois) EMIT_SIGNAL (XP_TE_WHOIS_SPECIAL, whois_sess, word[4], (word_eol[5][0] == ':') ? word_eol[5] + 1 : word_eol[5], word[2], NULL, 0); return; } def: if (is_channel (serv, word[4])) { session *realsess = find_channel (serv, word[4]); if (!realsess) realsess = serv->server_session; EMIT_SIGNAL (XP_TE_SERVTEXT, realsess, text, word[1], word[2], NULL, 0); } else { EMIT_SIGNAL (XP_TE_SERVTEXT, serv->server_session, text, word[1], word[2], NULL, 0); } } }
void handle_ctcp (struct session *sess, char *outbuf, char *to, char *nick, char *msg, char *word[], char *word_eol[]) { char *po; session *chansess; if (!strncasecmp (msg, "VERSION", 7) && !prefs.hidever) { sprintf (outbuf, "NOTICE %s :\001VERSION xchat "VERSION" %s (PicoGUI)\001\r\n", nick, get_cpu_str ()); tcp_send (sess->server, outbuf); } if (!ctcp_check (sess, outbuf, nick, word, word_eol, word[4] + 2)) { if (!strncasecmp (msg, "ACTION", 6)) { po = strchr (msg + 7, '\001'); if (po) po[0] = 0; channel_action (sess, outbuf, to, nick, msg + 7, FALSE); return; } if (!strncasecmp (msg, "DCC", 3)) { handle_dcc (sess, outbuf, nick, word, word_eol); return; } if (!strncasecmp (msg, "SOUND", 5)) { po = strchr (word[5], '\001'); if (po) po[0] = 0; EMIT_SIGNAL (XP_TE_CTCPSND, sess->server->front_session, word[5], nick, NULL, NULL, 0); sprintf (outbuf, "%s/%s", prefs.sounddir, word[5]); if (strchr (word[5], '/') == 0 && access (outbuf, R_OK) == 0) { sprintf (outbuf, "%s %s/%s", prefs.soundcmd, prefs.sounddir, word[5]); xchat_exec (outbuf); } return; } } po = strchr (msg, '\001'); if (po) po[0] = 0; if (!is_channel (sess->server, to)) { EMIT_SIGNAL (XP_TE_CTCPGEN, sess->server->front_session, msg, nick, NULL, NULL, 0); } else { chansess = find_session_from_channel (to, sess->server); if (chansess) { EMIT_SIGNAL (XP_TE_CTCPGENC, chansess, msg, nick, to, NULL, 0); return; } EMIT_SIGNAL (XP_TE_CTCPGENC, sess->server->front_session, msg, nick, to, NULL, 0); } }
void handle_mode (server * serv, char *word[], char *word_eol[], char *nick, int numeric_324) { session *sess; char *chan; char *modes; char *argstr; char sign; int len; int arg; int i, num_args; int num_modes; int offset = 3; int all_modes_have_args = FALSE; int using_front_tab = FALSE; mode_run mr; mr.serv = serv; mr.op = mr.deop = mr.voice = mr.devoice = NULL; /* numeric 324 has everything 1 word later (as opposed to MODE) */ if (numeric_324) offset++; chan = word[offset]; modes = word[offset + 1]; if (*modes == ':') modes++; if (*modes == 0) return; /* beyondirc's blank modes */ sess = find_channel (serv, chan); if (!sess) { sess = serv->front_session; using_front_tab = TRUE; } /* remove trailing space */ len = strlen (word_eol[offset]) - 1; if (word_eol[offset][len] == ' ') word_eol[offset][len] = 0; if (prefs.hex_irc_raw_modes && !numeric_324) EMIT_SIGNAL (XP_TE_RAWMODES, sess, nick, word_eol[offset], 0, 0, 0); if (numeric_324 && !using_front_tab) { if (sess->current_modes) free (sess->current_modes); sess->current_modes = strdup (word_eol[offset+1]); } sign = *modes; modes++; arg = 1; /* count the number of arguments (e.g. after the -o+v) */ num_args = 0; i = 1; while ((i + offset + 1) < PDIWORDS) { i++; if (!(*word[i + offset])) break; num_args++; } /* count the number of modes (without the -/+ chars */ num_modes = 0; i = 0; while (i < strlen (modes)) { if (modes[i] != '+' && modes[i] != '-') num_modes++; i++; } if (num_args == num_modes) all_modes_have_args = TRUE; while (*modes) { switch (*modes) { case '-': case '+': /* print all the grouped Op/Deops */ mode_print_grouped (sess, nick, &mr); sign = *modes; break; default: argstr = ""; if ((all_modes_have_args || mode_has_arg (serv, sign, *modes)) && arg < (num_args+1)) { arg++; argstr = word[arg + offset]; } handle_single_mode (&mr, sign, *modes, nick, chan, argstr, numeric_324 || prefs.hex_irc_raw_modes, numeric_324); } modes++; } /* update the title at the end, now that the mode update is internal now */ if (!using_front_tab) fe_set_title (sess); /* print all the grouped Op/Deops */ mode_print_grouped (sess, nick, &mr); }
void ctcp_handle (session *sess, char *to, char *nick, char *msg, char *word[], char *word_eol[], int id) { char *po; session *chansess; server *serv = sess->server; char outbuf[1024]; /* consider DCC to be different from other CTCPs */ if (!strncasecmp (msg, "DCC", 3)) { /* but still let CTCP replies override it */ if (!ctcp_check (sess, nick, word, word_eol, word[4] + 2)) { if (!ignore_check (word[1], IG_DCC)) handle_dcc (sess, nick, word, word_eol); } return; } /* consider ACTION to be different from other CTCPs. Check ignore as if it was a PRIV/CHAN. */ if (!strncasecmp (msg, "ACTION ", 7)) { if (is_channel (serv, to)) { /* treat a channel action as a CHAN */ if (ignore_check (word[1], IG_CHAN)) return; } else { /* treat a private action as a PRIV */ if (ignore_check (word[1], IG_PRIV)) return; } /* but still let CTCP replies override it */ if (ctcp_check (sess, nick, word, word_eol, word[4] + 2)) goto generic; inbound_action (sess, to, nick, msg + 7, FALSE, id); return; } if (ignore_check (word[1], IG_CTCP)) return; if (!strcasecmp (msg, "VERSION") && !prefs.hidever) { #ifdef FE_AQUA snprintf (outbuf, sizeof (outbuf), "VERSION X-Chat Aqua %s (xchat "PACKAGE_VERSION") %s", prefs.xchat_aqua_version, get_cpu_str ()); #else snprintf (outbuf, sizeof (outbuf), "VERSION xchat "PACKAGE_VERSION" %s", get_cpu_str ()); #endif serv->p_nctcp (serv, nick, outbuf); } if (!ctcp_check (sess, nick, word, word_eol, word[4] + 2)) { if (!strncasecmp (msg, "SOUND", 5)) { po = strchr (word[5], '\001'); if (po) po[0] = 0; if (is_channel (sess->server, to)) { chansess = find_channel (sess->server, to); if (!chansess) chansess = sess; EMIT_SIGNAL (XP_TE_CTCPSNDC, chansess, word[5], nick, to, NULL, 0); } else { EMIT_SIGNAL (XP_TE_CTCPSND, sess->server->front_session, word[5], nick, NULL, NULL, 0); } /* don't let IRCers specify path */ #ifdef WIN32 if (strchr (word[5], '/') == NULL && strchr (word[5], '\\') == NULL) #else if (strchr (word[5], '/') == NULL) #endif sound_play (word[5], TRUE); return; } } generic: po = strchr (msg, '\001'); if (po) po[0] = 0; if (!is_channel (sess->server, to)) { EMIT_SIGNAL (XP_TE_CTCPGEN, sess->server->front_session, msg, nick, NULL, NULL, 0); } else { chansess = find_channel (sess->server, to); if (!chansess) chansess = sess; EMIT_SIGNAL (XP_TE_CTCPGENC, chansess, msg, nick, to, NULL, 0); } }