diff options
Diffstat (limited to 'src')
37 files changed, 494 insertions, 214 deletions
diff --git a/src/common/chanopt.c b/src/common/chanopt.c index 1870c99c..67cb46cf 100644 --- a/src/common/chanopt.c +++ b/src/common/chanopt.c @@ -58,6 +58,7 @@ typedef struct static const channel_options chanopt[] = { + {"alert_balloon", NULL, S_F(alert_balloon)}, {"alert_beep", "BEEP", S_F(alert_beep)}, {"alert_taskbar", NULL, S_F(alert_taskbar)}, {"alert_tray", "TRAY", S_F(alert_tray)}, @@ -182,6 +183,7 @@ typedef struct { /* Per-Channel Alerts */ /* use a byte, because we need a pointer to each element */ + guint8 alert_balloon; guint8 alert_beep; guint8 alert_taskbar; guint8 alert_tray; diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 33a883bf..bc191f43 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Configuration">
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>v142</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
diff --git a/src/common/dcc.c b/src/common/dcc.c index 51f6d661..df129e68 100644 --- a/src/common/dcc.c +++ b/src/common/dcc.c @@ -1618,13 +1618,13 @@ dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc) } guint32 -dcc_get_my_address (void) /* the address we'll tell the other person */ +dcc_get_my_address (session *sess) /* the address we'll tell the other person */ { struct hostent *dns_query; guint32 addr = 0; - if (prefs.hex_dcc_ip_from_server && prefs.dcc_ip) - addr = prefs.dcc_ip; + if (prefs.hex_dcc_ip_from_server && sess->server->dcc_ip) + addr = sess->server->dcc_ip; else if (prefs.hex_dcc_ip[0]) { dns_query = gethostbyname ((const char *) prefs.hex_dcc_ip); @@ -1710,7 +1710,7 @@ dcc_listen_init (struct DCC *dcc, session *sess) /*if we have a dcc_ip, we use that, so the remote client can connect*/ /*else we try to take an address from hex_dcc_ip*/ /*if something goes wrong we tell the client to connect to our LAN ip*/ - dcc->addr = dcc_get_my_address (); + dcc->addr = dcc_get_my_address (sess); /*if nothing else worked we use the address we bound to*/ if (dcc->addr == 0) diff --git a/src/common/dcc.h b/src/common/dcc.h index 379385e6..74028205 100644 --- a/src/common/dcc.h +++ b/src/common/dcc.h @@ -124,7 +124,7 @@ void dcc_chat (session *sess, char *nick, int passive); void handle_dcc (session *sess, char *nick, char *word[], char *word_eol[], const message_tags_data *tags_data); void dcc_show_list (session *sess); -guint32 dcc_get_my_address (void); +guint32 dcc_get_my_address (session *sess); void dcc_get_with_destfile (struct DCC *dcc, char *utf8file); #endif diff --git a/src/common/hexchat.c b/src/common/hexchat.c index 347cf1ce..9be2e56d 100644 --- a/src/common/hexchat.c +++ b/src/common/hexchat.c @@ -493,6 +493,7 @@ session_new (server *serv, char *from, int type, int focus) sess->logfd = -1; sess->type = type; + sess->alert_balloon = SET_DEFAULT; sess->alert_beep = SET_DEFAULT; sess->alert_taskbar = SET_DEFAULT; sess->alert_tray = SET_DEFAULT; diff --git a/src/common/hexchat.h b/src/common/hexchat.h index 8c4a6a41..d8effa1f 100644 --- a/src/common/hexchat.h +++ b/src/common/hexchat.h @@ -75,7 +75,7 @@ #define DOMAINLEN 100 #define NICKLEN 64 /* including the NULL, so 63 really */ #define CHANLEN 300 -#define PDIWORDS 32 +#define PDIWORDS 32 #define USERNAMELEN 10 #define HIDDEN_CHAR 8 /* invisible character for xtext */ @@ -301,8 +301,8 @@ struct hexchatprefs char hex_irc_user_name[127]; char hex_net_bind_host[127]; char hex_net_proxy_host[64]; - char hex_net_proxy_pass[32]; - char hex_net_proxy_user[32]; + char hex_net_proxy_pass[256]; + char hex_net_proxy_user[256]; char hex_stamp_log_format[64]; char hex_stamp_text_format[64]; char hex_text_background[PATHLEN + 1]; @@ -313,7 +313,6 @@ struct hexchatprefs /* these are the private variables */ guint32 local_ip; - guint32 dcc_ip; unsigned int wait_on_exit; /* wait for logs to be flushed to disk IF we're connected */ @@ -364,6 +363,7 @@ typedef struct session { /* Per-Channel Alerts */ /* use a byte, because we need a pointer to each element */ + guint8 alert_balloon; guint8 alert_beep; guint8 alert_taskbar; guint8 alert_tray; @@ -482,6 +482,10 @@ typedef struct server int proxy_sok4; int proxy_sok6; int id; /* unique ID number (for plugin API) */ + + /* dcc_ip moved from hexchatprefs to make it per-server */ + guint32 dcc_ip; + #ifdef USE_OPENSSL SSL_CTX *ctx; SSL *ssl; @@ -566,6 +570,7 @@ typedef struct server unsigned int have_idmsg:1; /* freenode's IDENTIFY-MSG */ unsigned int have_accnotify:1; /* cap account-notify */ unsigned int have_extjoin:1; /* cap extended-join */ + unsigned int have_account_tag:1; /* cap account-tag */ unsigned int have_server_time:1; /* cap server-time */ unsigned int have_sasl:1; /* SASL capability */ unsigned int have_except:1; /* ban exemptions +e */ @@ -575,6 +580,7 @@ typedef struct server unsigned int sasl_mech; /* mechanism for sasl auth */ unsigned int sent_capend:1; /* have sent CAP END yet */ unsigned int waiting_on_cap:1; /* waiting on another line of CAP LS */ + unsigned int waiting_on_sasl:1; /* waiting on sasl */ #ifdef USE_OPENSSL unsigned int use_ssl:1; /* is server SSL capable? */ unsigned int accept_invalid_cert:1;/* ignore result of server's cert. verify */ diff --git a/src/common/inbound.c b/src/common/inbound.c index fb8eb511..7175b2ae 100644 --- a/src/common/inbound.c +++ b/src/common/inbound.c @@ -815,7 +815,9 @@ inbound_topictime (server *serv, char *chan, char *nick, time_t stamp, if (!sess) sess = serv->server_session; - tim[24] = 0; /* get rid of the \n */ + if (tim != NULL) + tim[24] = 0; /* get rid of the \n */ + EMIT_SIGNAL_TIMESTAMP (XP_TE_TOPICDATE, sess, chan, nick, tim, NULL, 0, tags_data->timestamp); } @@ -1420,7 +1422,7 @@ inbound_foundip (session *sess, char *ip, const message_tags_data *tags_data) HostAddr = gethostbyname (ip); if (HostAddr) { - prefs.dcc_ip = ((struct in_addr *) HostAddr->h_addr)->s_addr; + sess->server->dcc_ip = ((struct in_addr *) HostAddr->h_addr)->s_addr; EMIT_SIGNAL_TIMESTAMP (XP_TE_FOUNDIP, sess->server->server_session, inet_ntoa (*((struct in_addr *) HostAddr->h_addr)), NULL, NULL, NULL, 0, tags_data->timestamp); @@ -1489,7 +1491,7 @@ inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, server *serv = sess->server; char *nl; - if (stamp <= 0) + if (stamp <= 0 || time_str == NULL) { time_str = ""; } @@ -1669,6 +1671,8 @@ inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable) serv->have_server_time = enable; else if (!strcmp (extension, "away-notify")) serv->have_awaynotify = enable; + else if (!strcmp (extension, "account-tag")) + serv->have_account_tag = enable; else if (!strcmp (extension, "sasl")) { serv->have_sasl = enable; @@ -1722,6 +1726,9 @@ static const char * const supported_caps[] = { "userhost-in-names", "cap-notify", "chghost", + "setname", + "invite-notify", + "account-tag", /* ZNC */ "znc.in/server-time-iso", @@ -1768,7 +1775,6 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str, { char buffer[500]; /* buffer for requesting capabilities and emitting the signal */ gboolean want_cap = FALSE; /* format the CAP REQ string based on previous capabilities being requested or not */ - gboolean want_sasl = FALSE; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */ char **extensions; int i; @@ -1806,7 +1812,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str, /* if the SASL password is set AND auth mode is set to SASL, request SASL auth */ if (!g_strcmp0 (extension, "sasl") && ((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0) - || (serv->loginmethod == LOGIN_SASLEXTERNAL && serv->have_cert))) + || serv->loginmethod == LOGIN_SASLEXTERNAL)) { if (value) { @@ -1816,7 +1822,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str, serv->sasl_mech = sasl_mech; } want_cap = TRUE; - want_sasl = TRUE; + serv->waiting_on_sasl = TRUE; g_strlcat (buffer, "sasl ", sizeof(buffer)); continue; } @@ -1842,7 +1848,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str, tags_data->timestamp); tcp_sendf (serv, "%s\r\n", g_strchomp (buffer)); } - if (!want_sasl && !serv->waiting_on_cap) + if (!serv->waiting_on_sasl && !serv->waiting_on_cap) { /* if we use SASL, CAP END is dealt via raw numerics */ serv->sent_capend = TRUE; @@ -1851,13 +1857,25 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str, } void -inbound_cap_nak (server *serv, const message_tags_data *tags_data) +inbound_cap_nak (server *serv, char *extensions_str, const message_tags_data *tags_data) { - if (!serv->waiting_on_cap && !serv->sent_capend) + char **extensions; + int i; + + extensions = g_strsplit (extensions_str, " ", 0); + for (i=0; extensions[i]; i++) + { + if (!g_strcmp0 (extensions[i], "sasl")) + serv->waiting_on_sasl = FALSE; + } + + if (!serv->waiting_on_cap && !serv->waiting_on_sasl && !serv->sent_capend) { serv->sent_capend = TRUE; tcp_send_len (serv, "CAP END\r\n", 9); } + + g_strfreev (extensions); } void diff --git a/src/common/inbound.h b/src/common/inbound.h index 83e78d5d..6e7c171f 100644 --- a/src/common/inbound.h +++ b/src/common/inbound.h @@ -92,7 +92,7 @@ void inbound_cap_ack (server *serv, char *nick, char *extensions, const message_tags_data *tags_data); void inbound_cap_ls (server *serv, char *nick, char *extensions, const message_tags_data *tags_data); -void inbound_cap_nak (server *serv, const message_tags_data *tags_data); +void inbound_cap_nak (server *serv, char *extensions, const message_tags_data *tags_data); void inbound_cap_list (server *serv, char *nick, char *extensions, const message_tags_data *tags_data); void inbound_cap_del (server *serv, char *nick, char *extensions, diff --git a/src/common/meson.build b/src/common/meson.build index a0d6ce2b..492227b2 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -93,10 +93,6 @@ endif if get_option('with-plugin') common_deps += libgmodule_dep - common_cflags += '-DHEXCHATLIBDIR="@0@"'.format(join_paths(get_option('prefix'), - get_option('libdir'), - 'hexchat/plugins')) - install_headers('hexchat-plugin.h') endif @@ -109,6 +105,7 @@ hexchat_common = static_library('hexchatcommon', ) hexchat_common_dep = declare_dependency( + sources: [textevents] + marshal, link_with: hexchat_common, include_directories: common_includes, compile_args: common_cflags, diff --git a/src/common/modes.c b/src/common/modes.c index c65bf279..3c0ac8ab 100644 --- a/src/common/modes.c +++ b/src/common/modes.c @@ -735,6 +735,8 @@ handle_mode (server * serv, char *word[], char *word_eol[], if (!(*word[i + offset])) break; num_args++; + if (word[i + offset][0] == ':') + break; } /* count the number of modes (without the -/+ chars */ @@ -765,7 +767,7 @@ handle_mode (server * serv, char *word[], char *word_eol[], if ((all_modes_have_args || mode_has_arg (serv, sign, *modes)) && arg < (num_args + 1)) { arg++; - argstr = word[arg + offset]; + argstr = STRIP_COLON(word, word_eol, arg+offset); } handle_single_mode (&mr, sign, *modes, nick, chan, argstr, numeric_324 || prefs.hex_irc_raw_modes, diff --git a/src/common/outbound.c b/src/common/outbound.c index 96fb7fe4..614aad38 100644 --- a/src/common/outbound.c +++ b/src/common/outbound.c @@ -3287,7 +3287,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[]) if (!word[2][0]) return FALSE; - addr = dcc_get_my_address (); + addr = dcc_get_my_address (sess); if (addr == 0) { /* use the one from our connected server socket */ diff --git a/src/common/plugin.c b/src/common/plugin.c index 0aa8859d..d3f3b7ca 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -115,6 +115,34 @@ enum HOOK_DELETED = 1 << 7 /* marked for deletion */ }; +enum +{ + CHANNEL_FLAG_CONNECTED = 1 << 0, + CHANNEL_FLAG_CONNECING = 1 << 1, + CHANNEL_FLAG_AWAY = 1 << 2, + CHANNEL_FLAG_END_OF_MOTD = 1 << 3, + CHANNEL_FLAG_HAS_WHOX = 1 << 4, + CHANNEL_FLAG_HAS_IDMSG = 1 << 5, + CHANNEL_FLAG_HIDE_JOIN_PARTS = 1 << 6, + CHANNEL_FLAG_HIDE_JOIN_PARTS_UNSET = 1 << 7, + CHANNEL_FLAG_BEEP = 1 << 8, + CHANNEL_FLAG_BEEP_UNSET = 1 << 9, + CHANNEL_FLAG_UNUSED = 1 << 10, + CHANNEL_FLAG_LOGGING = 1 << 11, + CHANNEL_FLAG_LOGGING_UNSET = 1 << 12, + CHANNEL_FLAG_SCROLLBACK = 1 << 13, + CHANNEL_FLAG_SCROLLBACK_UNSET = 1 << 14, + CHANNEL_FLAG_STRIP_COLORS = 1 << 15, + CHANNEL_FLAG_STRIP_COLORS_UNSET = 1 << 16, + CHANNEL_FLAG_TRAY = 1 << 17, + CHANNEL_FLAG_TRAY_UNSET = 1 << 18, + CHANNEL_FLAG_TASKBAR = 1 << 19, + CHANNEL_FLAG_TASKBAR_UNSET = 1 << 20, + CHANNEL_FLAG_BALLOON = 1 << 21, + CHANNEL_FLAG_BALLOON_UNSET = 1 << 22, + CHANNEL_FLAG_COUNT = 23 +}; + GSList *plugin_list = NULL; /* export for plugingui.c */ static GSList *hook_list = NULL; @@ -355,7 +383,8 @@ plugin_kill_all (void) } } -#ifdef USE_PLUGIN +#if defined(USE_PLUGIN) || defined(WIN32) +/* used for loading plugins, and in fe-gtk/notifications/notification-windows.c */ GModule * module_load (char *filename) @@ -384,6 +413,10 @@ module_load (char *filename) return handle; } +#endif + +#ifdef USE_PLUGIN + /* load a plugin from a filename. Returns: NULL-success or an error string */ char * @@ -676,11 +709,11 @@ check_and_invalidate(void *plug_, void *killsess_) int plugin_emit_dummy_print (session *sess, char *name) { - char *word[32]; + char *word[PDIWORDS]; int i; word[0] = name; - for (i = 1; i < 32; i++) + for (i = 1; i < PDIWORDS; i++) word[i] = "\000"; i = plugin_hook_run (sess, name, word, NULL, NULL, HOOK_PRINT); @@ -1544,7 +1577,11 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name) { guint32 hash = str_hash (name); gpointer data = ph->context; - int tmp = 0; + + int channel_flag; + int channel_flags[CHANNEL_FLAG_COUNT]; + int channel_flags_used = 0; + int type = LIST_CHANNELS; /* a NULL xlist is a shortcut to current "channels" context */ @@ -1605,48 +1642,38 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name) case 0xd1b: /* id */ return ((struct session *)data)->server->id; case 0x5cfee87: /* flags */ - /* used if alert_taskbar is unset */ /* 20 */ - tmp <<= 1; - tmp |= ((struct session *)data)->alert_taskbar; /* 19 */ - tmp <<= 1; - /* used if alert_tray is unset */ /* 18 */ - tmp <<= 1; - tmp |= ((struct session *)data)->alert_tray; /* 17 */ - tmp <<= 1; - /* used if text_strip is unset */ /* 16 */ - tmp <<= 1; - tmp |= ((struct session *)data)->text_strip; /* 15 */ - tmp <<= 1; - /* used if text_scrollback is unset */ /* 14 */ - tmp <<= 1; - tmp |= ((struct session *)data)->text_scrollback; /* 13 */ - tmp <<= 1; - /* used if text_logging is unset */ /* 12 */ - tmp <<= 1; - tmp |= ((struct session *)data)->text_logging; /* 11 */ - tmp <<= 1; - /* unused for historical reasons */ /* 10 */ - tmp <<= 1; - /* used if alert_beep is unset */ /* 9 */ - tmp <<= 1; - tmp |= ((struct session *)data)->alert_beep; /* 8 */ - tmp <<= 1; - /* used if text_hidejoinpart is unset */ /* 7 */ - tmp <<= 1; - tmp |= ((struct session *)data)->text_hidejoinpart; /* 6 */ - tmp <<= 1; - tmp |= ((struct session *)data)->server->have_idmsg; /* 5 */ - tmp <<= 1; - tmp |= ((struct session *)data)->server->have_whox; /* 4 */ - tmp <<= 1; - tmp |= ((struct session *)data)->server->end_of_motd;/* 3 */ - tmp <<= 1; - tmp |= ((struct session *)data)->server->is_away; /* 2 */ - tmp <<= 1; - tmp |= ((struct session *)data)->server->connecting; /* 1 */ - tmp <<= 1; - tmp |= ((struct session *)data)->server->connected; /* 0 */ - return tmp; + channel_flags[0] = ((struct session *)data)->server->connected; + channel_flags[1] = ((struct session *)data)->server->connecting; + channel_flags[2] = ((struct session *)data)->server->is_away; + channel_flags[3] = ((struct session *)data)->server->end_of_motd; + channel_flags[4] = ((struct session *)data)->server->have_whox; + channel_flags[5] = ((struct session *)data)->server->have_idmsg; + channel_flags[6] = ((struct session *)data)->text_hidejoinpart; + channel_flags[7] = ((struct session *)data)->text_hidejoinpart == SET_DEFAULT; + channel_flags[8] = ((struct session *)data)->alert_beep; + channel_flags[9] = ((struct session *)data)->alert_beep == SET_DEFAULT; + channel_flags[10] = 0; /* unused for historical reasons */ + channel_flags[11] = ((struct session *)data)->text_logging; + channel_flags[12] = ((struct session *)data)->text_logging == SET_DEFAULT; + channel_flags[13] = ((struct session *)data)->text_scrollback; + channel_flags[14] = ((struct session *)data)->text_scrollback == SET_DEFAULT; + channel_flags[15] = ((struct session *)data)->text_strip; + channel_flags[16] = ((struct session *)data)->text_strip == SET_DEFAULT; + channel_flags[17] = ((struct session *)data)->alert_tray; + channel_flags[18] = ((struct session *)data)->alert_tray == SET_DEFAULT; + channel_flags[19] = ((struct session *)data)->alert_taskbar; + channel_flags[20] = ((struct session *)data)->alert_taskbar == SET_DEFAULT; + channel_flags[21] = ((struct session *)data)->alert_balloon; + channel_flags[22] = ((struct session *)data)->alert_balloon == SET_DEFAULT; + + /* Set flags */ + for (channel_flag = 0; channel_flag < CHANNEL_FLAG_COUNT; ++channel_flag) { + if (channel_flags[channel_flag]) { + channel_flags_used |= 1 << channel_flag; + } + } + + return channel_flags_used; case 0x1a192: /* lag */ return ((struct session *)data)->server->lag; case 0x1916144c: /* maxmodes */ diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c index 776d1434..c8e44b62 100644 --- a/src/common/proto-irc.c +++ b/src/common/proto-irc.c @@ -60,8 +60,8 @@ irc_login (server *serv, char *user, char *realname) tcp_sendf (serv, "NICK %s\r\n" - "USER %s %s %s :%s\r\n", - serv->nick, user, user, serv->servername, realname); + "USER %s 0 * :%s\r\n", + serv->nick, user, realname); } static void @@ -454,7 +454,8 @@ channel_date (session *sess, char *chan, char *timestr, { time_t timestamp = (time_t) atol (timestr); char *tim = ctime (×tamp); - tim[24] = 0; /* get rid of the \n */ + if (tim != NULL) + tim[24] = 0; /* get rid of the \n */ EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANDATE, sess, chan, tim, NULL, NULL, 0, tags_data->timestamp); } @@ -602,7 +603,8 @@ process_numeric (session * sess, int n, else { tim = ctime (×tamp); - tim[19] = 0; /* get rid of the \n */ + if (tim != NULL) + tim[19] = 0; /* get rid of the \n */ EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS4T, whois_sess, word[4], outbuf, tim, NULL, 0, tags_data->timestamp); } @@ -621,7 +623,7 @@ process_numeric (session * sess, int n, case 319: if (!serv->skip_next_whois) EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS2, whois_sess, word[4], - word_eol[5] + 1, NULL, NULL, 0, + word_eol[5][0] == ':' ? word_eol[5] + 1 : word_eol[5], NULL, NULL, 0, tags_data->timestamp); break; @@ -714,7 +716,7 @@ process_numeric (session * sess, int n, break; case 333: - inbound_topictime (serv, word[4], word[5], atol (word[6]), tags_data); + inbound_topictime (serv, word[4], word[5], atol (STRIP_COLON(word, word_eol, 6)), tags_data); break; #if 0 @@ -726,7 +728,7 @@ process_numeric (session * sess, int n, #endif case 341: /* INVITE ACK */ - EMIT_SIGNAL_TIMESTAMP (XP_TE_UINVITE, sess, word[4], word[5], + EMIT_SIGNAL_TIMESTAMP (XP_TE_UINVITE, sess, word[4], STRIP_COLON(word, word_eol, 5), serv->servername, NULL, 0, tags_data->timestamp); break; @@ -957,6 +959,7 @@ process_numeric (session * sess, int n, EMIT_SIGNAL_TIMESTAMP (XP_TE_SASLRESPONSE, serv->server_session, word[1], word[2], word[3], ++word_eol[4], 0, tags_data->timestamp); + serv->waiting_on_sasl = FALSE; if (!serv->sent_capend) { serv->sent_capend = TRUE; @@ -1007,6 +1010,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], const message_tags_data *tags_data) { server *serv = sess->server; + char *account; char ip[128], nick[NICKLEN]; char *text, *ex; int len = strlen (type); @@ -1025,6 +1029,14 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], ex[0] = '!'; } + + /** Update the account for this message's source. */ + if (serv->have_account_tag) + { + account = tags_data->account && *tags_data->account ? tags_data->account : "*"; + inbound_account (serv, nick, account, tags_data); + } + if (len == 4) { guint32 t; @@ -1142,7 +1154,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], { case WORDL('A','C','C','O'): - inbound_account (serv, nick, word[3], tags_data); + inbound_account (serv, nick, STRIP_COLON(word, word_eol, 3), tags_data); return; case WORDL('A', 'U', 'T', 'H'): @@ -1150,20 +1162,26 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], return; case WORDL('C', 'H', 'G', 'H'): - inbound_user_info (sess, NULL, word[3], word[4], NULL, nick, NULL, + inbound_user_info (sess, NULL, word[3], STRIP_COLON(word, word_eol, 4), NULL, nick, NULL, + NULL, 0xff, tags_data); + return; + + case WORDL('S', 'E', 'T', 'N'): + inbound_user_info (sess, NULL, NULL, NULL, NULL, nick, STRIP_COLON(word, word_eol, 3), NULL, 0xff, 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, + + text = STRIP_COLON(word, word_eol, 4); + if (serv->p_cmp (word[3], serv->nick)) + EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITEDOTHER, sess, text, nick, + word[3], serv->servername, 0, tags_data->timestamp); else - EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, word[4], nick, + EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, text, nick, serv->servername, NULL, 0, tags_data->timestamp); @@ -1241,10 +1259,13 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], text++; } len = strlen (text); - if (text[0] == 1 && text[len - 1] == 1) /* ctcp */ + if (text[0] == 1) /* ctcp */ { char *new_pdibuf = NULL; - text[len - 1] = 0; + if (text[len - 1] == 1) + { + text[len - 1] = 0; + } text++; if (g_ascii_strncasecmp (text, "ACTION", 6) != 0) flood_check (nick, ip, serv, sess, 0); @@ -1330,7 +1351,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], } else if (strncasecmp (word[4], "NAK", 3) == 0) { - inbound_cap_nak (serv, tags_data); + inbound_cap_nak (serv, word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5], tags_data); } else if (strncasecmp (word[4], "LIST", 4) == 0) { @@ -1513,6 +1534,9 @@ handle_message_tags (server *serv, const char *tags_str, *value = '\0'; value++; + if (serv->have_account_tag && !strcmp (key, "account")) + tags_data->account = g_strdup (value); + if (serv->have_server_time && !strcmp (key, "time")) handle_message_tag_time (value, tags_data); } @@ -1610,10 +1634,17 @@ irc_inline (server *serv, char *buf, int len) } xit: + message_tags_data_free (&tags_data); g_free (pdibuf); } void +message_tags_data_free (message_tags_data *tags_data) +{ + g_clear_pointer (&tags_data->account, g_free); +} + +void proto_fill_her_up (server *serv) { serv->p_inline = irc_inline; diff --git a/src/common/proto-irc.h b/src/common/proto-irc.h index a7b4029c..0f72c644 100644 --- a/src/common/proto-irc.h +++ b/src/common/proto-irc.h @@ -25,18 +25,24 @@ #define MESSAGE_TAGS_DATA_INIT \ { \ + NULL, /* account name */ \ (time_t)0, /* timestamp */ \ } +#define STRIP_COLON(word, word_eol, idx) (word)[(idx)][0] == ':' ? (word_eol)[(idx)]+1 : (word)[(idx)] + /* Message tag information that might be passed along with a server message * * See http://ircv3.atheme.org/specification/capability-negotiation-3.1 */ typedef struct { + char *account; time_t timestamp; } message_tags_data; +void message_tags_data_free (message_tags_data *tags_data); + void proto_fill_her_up (server *serv); #endif |