summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/chanopt.c2
-rw-r--r--src/common/common.vcxproj2
-rw-r--r--src/common/dcc.c8
-rw-r--r--src/common/dcc.h2
-rw-r--r--src/common/hexchat.c1
-rw-r--r--src/common/hexchat.h14
-rw-r--r--src/common/inbound.c36
-rw-r--r--src/common/inbound.h2
-rw-r--r--src/common/meson.build5
-rw-r--r--src/common/modes.c4
-rw-r--r--src/common/outbound.c2
-rw-r--r--src/common/plugin.c119
-rw-r--r--src/common/proto-irc.c65
-rw-r--r--src/common/proto-irc.h6
-rw-r--r--src/common/server.c56
-rw-r--r--src/common/servlist.c61
-rw-r--r--src/common/text.c7
-rw-r--r--src/common/textevents.in6
-rw-r--r--src/common/url.c2
-rw-r--r--src/common/userlist.c17
-rw-r--r--src/fe-gtk/fe-gtk.c4
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj2
-rw-r--r--src/fe-gtk/joind.c2
-rw-r--r--src/fe-gtk/maingui.c30
-rw-r--r--src/fe-gtk/menu.c20
-rw-r--r--src/fe-gtk/meson.build13
-rw-r--r--src/fe-gtk/notifications/notifications-winrt.vcxproj126
-rw-r--r--src/fe-gtk/pixmaps.c22
-rw-r--r--src/fe-gtk/plugin-notification.c40
-rw-r--r--src/fe-gtk/xtext.c18
-rw-r--r--src/fe-text/fe-text.c2
-rw-r--r--src/fe-text/fe-text.vcxproj2
-rw-r--r--src/htm/Properties/Resources.Designer.cs2
-rw-r--r--src/htm/Properties/Settings.Designer.cs2
-rw-r--r--src/htm/app.config2
-rw-r--r--src/htm/htm.csproj2
-rw-r--r--src/libenchant_win8/libenchant_win8.vcxproj2
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 (&timestamp);
- 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 (&timestamp);
- 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
diff --git a/src/common/server.c b/src/common/server.c
index 3db0a963..5c645eb5 100644
--- a/src/com