📄 inbound.c
字号:
/* X-Chat * Copyright (C) 1998 Peter Zelezny. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */#include <string.h>#include <ctype.h>#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <time.h>#define WANTARPA#define WANTDNS#include "inet.h"#include "xchat.h"#include "util.h"#include "ignore.h"#include "plugin.h"#include "perlc.h"#include "fe.h"#include "modes.h"#include "notify.h"#include "outbound.h"#include "inbound.h"#include "text.h"#include "ctcp.h"#include "xchatc.h"/* black n white(0/1) are bad colors for nicks, and we'll use color 2 for us *//* also light/dark gray (14/15) *//* 5,7,8 are all shades of yellow which happen to look dman near the same */static int rcolors[] = { 3, 4, 6, 8, 9, 10, 11, 12, 13 };static intcolor_of (char *name){ int i = 0, sum = 0; while (name[i]) sum += name[i++]; sum %= sizeof (rcolors) / sizeof (int); return rcolors[sum];}voidclear_channel (struct session *sess){ if (prefs.persist_chans) safe_strcpy (sess->waitchannel, sess->channel, CHANLEN); sess->channel[0] = 0; if (sess->logfd != -1) { end_logging (sess->logfd); sess->logfd = -1; } free (sess->current_modes); sess->current_modes = strdup (""); if (sess->mode_timeout_tag) { fe_timeout_remove (sess->mode_timeout_tag); sess->mode_timeout_tag = 0; } fe_clear_channel (sess); clear_user_list (sess); fe_set_nonchannel (sess, FALSE); fe_set_title (sess);}voidset_topic(struct session *sess, char *topic){ if (sess->topic) free(sess->topic); sess->topic = strdup(topic); fe_set_topic(sess, topic);}static session *find_session_from_nick (char *nick, server *serv){ session *sess; GSList *list = sess_list; sess = find_session_from_channel (nick, serv); if (sess) return sess; if (serv->front_session) { if (find_name (serv->front_session, nick)) return serv->front_session; } if (menu_sess && menu_sess->server == serv) { if (find_name (menu_sess, nick)) return menu_sess; } while (list) { sess = list->data; if (sess->server == serv) { if (find_name (sess, nick)) return sess; } list = list->next; } return 0;}voidprivate_msg (struct server *serv, char *tbuf, char *from, char *ip, char *text){ struct session *sess; if (EMIT_SIGNAL (XP_PRIVMSG, serv, from, ip, text, NULL, 0) == 1) return; sess = find_session_from_channel (from, serv); if (((sess) && fe_is_beep (sess)) || prefs.beepmsg) fe_beep (); if (sess || prefs.autodialog) { /*0=ctcp 1=priv will set autodialog=0 here is flud detected */ if (!sess) { if (flood_check (from, ip, serv, menu_sess, 1)) sess = new_ircwindow (serv, from, SESS_DIALOG); /* Create a dialog session */ else sess = serv->front_session; } if (prefs.logging && sess->logfd != -1 && ip && *ip && (!sess->topic || strcmp(sess->topic, ip))) { char temp[512]; snprintf(temp, sizeof(temp), "[%s has address %s]\n", from, ip); write(sess->logfd, temp, strlen(temp)); } channel_msg (serv, tbuf, from, from, text, FALSE); if (ip && ip[0]) set_topic (sess, ip); return; } sess = find_session_from_nick (from, serv); if (!sess) sess = serv->front_session; EMIT_SIGNAL (XP_TE_PRIVMSG, sess, from, text, NULL, NULL, 0);}static intSearchNick (char *text, char *nicks){ char S[300]; /* size of bluestring in xchatprefs */ char *n; char *p; char *t; size_t ns; if (nicks == NULL) return 0; text = strip_color (text); safe_strcpy (S, nicks, sizeof (S)); n = strtok (S, ","); while (n != NULL) { t = text; ns = strlen (n); while ((p = nocasestrstr (t, n))) { if ((p == text || !isalnum (*(p - 1))) && !isalnum (*(p + ns))) { free (text); return 1; } t = p + 1; } n = strtok (NULL, ","); } free (text); return 0;}static intis_hilight (char *from, char *text, char *chan, session *sess, server *serv){ if ((prefs.hilightnick && SearchNick (text, serv->nick)) || SearchNick (text, prefs.bluestring)) { if (EMIT_SIGNAL (XP_HIGHLIGHT, sess, chan, from, text, NULL, 0) == 1) return 2; if (sess != current_tab && sess->is_tab) { sess->nick_said = TRUE; fe_set_hilight (sess); } return 1; } return 0;}voidchannel_action (session *sess, char *tbuf, char *chan, char *from, char *text, int fromme){ int hilight = FALSE; session *def = sess; server *serv = sess->server; if (EMIT_SIGNAL (XP_CHANACTION, sess, chan, from, text, NULL, fromme) == 1) return; if (is_channel (serv, chan) || fromme) { sess = find_session_from_channel (chan, serv); if (!fromme && sess) if (fe_is_beep (sess) || prefs.beepchans) fe_beep (); } else { /* it's a private action! */ sess = find_session_from_channel (from, serv); if (((sess) && fe_is_beep (sess)) || prefs.beepmsg) fe_beep (); } if (!sess && !is_channel (serv, chan) && prefs.autodialog) sess = new_ircwindow (serv, from, SESS_DIALOG); if (!sess) sess = def; if (!fromme) { switch (is_hilight (from, text, chan, sess, serv)) { case 2: return; /* plugin ate the event */ case 1: hilight = TRUE; } } sess->highlight_tab = TRUE; if (hilight) { EMIT_SIGNAL (XP_TE_HCHANACTION, sess, from, text, NULL, NULL, 0); } else if (prefs.colorednicks) { sprintf (tbuf, "\003%d%s", color_of (from), from); EMIT_SIGNAL (XP_TE_CHANACTION, sess, tbuf, text, NULL, NULL, 0); } else { EMIT_SIGNAL (XP_TE_CHANACTION, sess, from, text, NULL, NULL, 0); }}voidchannel_msg (struct server *serv, char *outbuf, char *chan, char *from, char *text, char fromme){ struct User *user; struct session *sess; int hilight = FALSE; char nickchar[2] = "\000"; sess = find_session_from_channel (chan, serv); if (!sess) return; sess->highlight_tab = TRUE; user = find_name (sess, from); if (user) { nickchar[0] = user->prefix; if (nickchar[0] == ' ') nickchar[0] = 0; user->lasttalk = time (0); } if (EMIT_SIGNAL (XP_CHANMSG, serv, chan, from, text, NULL, fromme) == 1) return; if (!fromme) { switch (is_hilight (from, text, chan, sess, serv)) { case 2: return; /* plugin ate the event */ case 1: hilight = TRUE; } } if (fromme) EMIT_SIGNAL (XP_TE_UCHANMSG, sess, from, text, nickchar, NULL, 0); else if (sess->type == SESS_DIALOG) EMIT_SIGNAL (XP_TE_DPRIVMSG, sess, from, text, nickchar, NULL, 0); else if (hilight) EMIT_SIGNAL (XP_TE_HCHANMSG, sess, from, text, nickchar, NULL, 0); else if (prefs.colorednicks) { sprintf (outbuf, "\003%d%s", color_of (from), from); EMIT_SIGNAL (XP_TE_CHANMSG, sess, outbuf, text, nickchar, NULL, 0); } else EMIT_SIGNAL (XP_TE_CHANMSG, sess, from, text, nickchar, NULL, 0); if (!fromme && sess->type != SESS_DIALOG) if (fe_is_beep (sess) || prefs.beepchans) fe_beep ();}voiduser_new_nick (struct server *serv, char *nick, char *newnick, int quiet){ int me; struct session *sess; GSList *list = sess_list; if (*newnick == ':') newnick++; if (!strcasecmp (nick, serv->nick)) { me = TRUE; safe_strcpy (serv->nick, newnick, NICKLEN); } else me = FALSE; if (EMIT_SIGNAL (XP_CHANGENICK, serv, nick, newnick, NULL, NULL, me) == 1) return; while (list) { sess = (struct session *) list->data; if (sess->server == serv) { if (me || find_name (sess, nick)) { if (!quiet) { if (me) EMIT_SIGNAL (XP_TE_UCHANGENICK, sess, nick, newnick, NULL, NULL, 0); else EMIT_SIGNAL (XP_TE_CHANGENICK, sess, nick, newnick, NULL, NULL, 0); } change_nick (sess, nick, newnick); } if (!strcasecmp (sess->channel, nick)) { safe_strcpy (sess->channel, newnick, CHANLEN); fe_set_channel (sess); } fe_set_title (sess); } list = list->next; } fe_change_nick (serv, nick, newnick); dcc_change_nick (serv, nick, newnick); if (me) fe_set_nick (serv, newnick);}/* find a "<none>" tab */static session *find_unused_session (server *serv){ session *sess; GSList *list = sess_list; while (list) { sess = (session *) list->data; if (sess->type == SESS_CHANNEL && sess->channel[0] == 0 && sess->server == serv) { if (!prefs.persist_chans || sess->waitchannel[0] == 0) return sess; } list = list->next; } return 0;}static session *find_session_from_waitchannel (char *chan, struct server *serv){ struct session *sess; GSList *list = sess_list; while (list) { sess = (struct session *) list->data; if (sess->server == serv && sess->channel[0] == 0 && sess->type == SESS_CHANNEL) { if (!strcasecmp (chan, sess->waitchannel)) return sess; } list = list->next; } return 0;}static voidyou_joined (server *serv, char *outbuf, char *chan, char *nick, char *ip){ session *sess; /* already joined? probably a bnc */ sess = find_session_from_channel (chan, serv); 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, NULL, 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) setup_logging (sess); sess->waitchannel[0] = 0; sess->ignore_date = TRUE; sess->ignore_mode = TRUE; sess->ignore_names = TRUE; sess->end_of_names = FALSE; sprintf (outbuf, "MODE %s\r\n", chan); tcp_send (sess->server, outbuf); EMIT_SIGNAL (XP_TE_UJOIN, sess, nick, chan, ip, NULL, 0); if (prefs.userhost) { sprintf (outbuf, "WHO %s\r\n", sess->channel); tcp_send (serv, outbuf); sess->doing_who = TRUE; }}static voidyou_kicked (struct server *serv, char *tbuf, char *chan, char *kicker, char *reason){ struct session *sess = find_session_from_channel (chan, serv); if (sess) { EMIT_SIGNAL (XP_TE_UKICK, sess, serv->nick, chan, kicker, reason, 0); clear_channel (sess); if (prefs.autorejoin) { if (sess->channelkey[0] == '\0') sprintf (tbuf, "JOIN %s\r\n", chan); else sprintf (tbuf, "JOIN %s %s\r\n", chan, sess->channelkey); tcp_send (sess->server, tbuf); safe_strcpy (sess->waitchannel, chan, CHANLEN); } }}static voidyou_parted (struct server *serv, char *chan, char *ip, char *reason){ struct session *sess = find_session_from_channel (chan, serv); if (sess) { if (*reason) EMIT_SIGNAL (XP_TE_UPARTREASON, sess, serv->nick, ip, chan, reason, 0); else EMIT_SIGNAL (XP_TE_UPART, sess, serv->nick, ip, chan, NULL, 0); clear_channel (sess); }}static voidnames_list (server *serv, char *chan, char *names){ struct session *sess; char name[NICKLEN]; int pos = 0; sess = find_session_from_channel (chan, serv); if (!sess) { EMIT_SIGNAL (XP_TE_USERSONCHAN, serv->front_session, chan, names, NULL, NULL, 0); return; } if (!sess->ignore_names) EMIT_SIGNAL (XP_TE_USERSONCHAN, sess, chan, names, NULL, NULL, 0); if (sess->end_of_names) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -