summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2018-05-20 15:21:07 +0200
committerSébastien Helleu <flashcode@flashtux.org>2018-05-20 15:21:07 +0200
commitafb1d0305313edef297e2f1f6ced9058a4560556 (patch)
tree789625c55c21c377a2618c709bfef2b56ad90693 /src/plugins
parent0329a9c7cde1334d0de17440b6d2d304bdf2e6eb (diff)
parent0a348f0b9dd31fe8546e61d445f23b44a26d1abf (diff)
downloadweechat-afb1d0305313edef297e2f1f6ced9058a4560556.zip
Merge remote-tracking branch 'origin/pr/623' into irc-3.2-cap
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/irc/irc-channel.c4
-rw-r--r--src/plugins/irc/irc-command.c30
-rw-r--r--src/plugins/irc/irc-protocol.c495
-rw-r--r--src/plugins/irc/irc-server.c52
-rw-r--r--src/plugins/irc/irc-server.h10
-rw-r--r--src/plugins/irc/irc-upgrade.c24
-rw-r--r--src/plugins/plugin.c1
-rw-r--r--src/plugins/weechat-plugin.h10
8 files changed, 425 insertions, 201 deletions
diff --git a/src/plugins/irc/irc-channel.c b/src/plugins/irc/irc-channel.c
index 4b6534c5e..ab24038a0 100644
--- a/src/plugins/irc/irc-channel.c
+++ b/src/plugins/irc/irc-channel.c
@@ -699,8 +699,8 @@ irc_channel_check_whox (struct t_irc_server *server,
{
if ((channel->type == IRC_CHANNEL_TYPE_CHANNEL) && channel->nicks)
{
- if (server->cap_away_notify
- || server->cap_account_notify
+ if (weechat_hashtable_has_key (server->cap_list, "away-notify")
+ || weechat_hashtable_has_key (server->cap_list, "account-notify")
|| ((IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK) > 0)
&& ((IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS) == 0)
|| (channel->nicks_count <= IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS)))))
diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c
index f4703866a..22a1977e2 100644
--- a/src/plugins/irc/irc-command.c
+++ b/src/plugins/irc/irc-command.c
@@ -1223,6 +1223,8 @@ IRC_COMMAND_CALLBACK(ban)
IRC_COMMAND_CALLBACK(cap)
{
+ char *cap_cmd;
+
IRC_BUFFER_GET_SERVER(buffer);
IRC_COMMAND_CHECK_SERVER("cap", 1);
@@ -1232,11 +1234,27 @@ IRC_COMMAND_CALLBACK(cap)
if (argc > 1)
{
- irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
- "CAP %s%s%s",
- argv[1],
- (argv_eol[2]) ? " :" : "",
- (argv_eol[2]) ? argv_eol[2] : "");
+ cap_cmd = strdup (argv[1]);
+ if (!cap_cmd)
+ WEECHAT_COMMAND_ERROR;
+
+ weechat_string_toupper (cap_cmd);
+
+ if ((weechat_strcasecmp (argv[1], "ls") == 0) && !argv_eol[2])
+ {
+ irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
+ "CAP LS " IRC_SERVER_VERSION_CAP);
+ }
+ else
+ {
+ irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
+ "CAP %s%s%s",
+ cap_cmd,
+ (argv_eol[2]) ? " :" : "",
+ (argv_eol[2]) ? argv_eol[2] : "");
+ }
+
+ free (cap_cmd);
}
else
{
@@ -1245,7 +1263,7 @@ IRC_COMMAND_CALLBACK(cap)
* enabled
*/
irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
- "CAP LS");
+ "CAP LS " IRC_SERVER_VERSION_CAP);
irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
"CAP LIST");
}
diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c
index be9f62f51..340eb6589 100644
--- a/src/plugins/irc/irc-protocol.c
+++ b/src/plugins/irc/irc-protocol.c
@@ -208,11 +208,15 @@ IRC_PROTOCOL_CALLBACK(account)
struct t_irc_channel *ptr_channel;
struct t_irc_nick *ptr_nick;
char *pos_account;
+ int cap_account_notify;
IRC_PROTOCOL_MIN_ARGS(3);
pos_account = (strcmp (argv[2], "*") != 0) ? argv[2] : NULL;
+ cap_account_notify = weechat_hashtable_has_key (server->cap_list,
+ "account-notify");
+
for (ptr_channel = server->channels; ptr_channel;
ptr_channel = ptr_channel->next_channel)
{
@@ -221,7 +225,7 @@ IRC_PROTOCOL_CALLBACK(account)
{
if (ptr_nick->account)
free (ptr_nick->account);
- ptr_nick->account = (server->cap_account_notify && pos_account) ?
+ ptr_nick->account = (cap_account_notify && pos_account) ?
strdup (pos_account) : NULL;
}
}
@@ -331,6 +335,146 @@ IRC_PROTOCOL_CALLBACK(away)
}
/*
+ * Callback for IRC server capabilities string length hashtable map.
+ */
+
+void irc_protocol_cap_length_cb (void *data,
+ struct t_hashtable *hashtable,
+ const char *key, const char *value)
+{
+ int *length;
+
+ /* make C compiler happy */
+ (void) hashtable;
+
+ length = (int*)data;
+ *length += 1 + strlen (key); // separator + key
+ if (value)
+ *length += 1 + strlen (value); // equals sign + value
+}
+
+/*
+ * Callback for IRC server capabilities string hashtable map.
+ */
+
+void irc_protocol_cap_print_cb (void *data,
+ struct t_hashtable *hashtable,
+ const char *key, const char *value)
+{
+ char *str, *pos;
+
+ /* make C compiler happy */
+ (void) hashtable;
+
+ str = (char*)data;
+ pos = str + strlen (str);
+
+ sprintf (pos, " %s%s%s",
+ key,
+ (value) ? "=" : "",
+ (value) ? value : "");
+}
+
+/*
+ * Synchronize requested capabilities for IRC server
+ */
+
+void irc_protocol_cap_sync (struct t_irc_server *server, int sasl)
+{
+ char *cap_option, *cap_req, **caps_requested;
+ const char *ptr_cap_option;
+ int sasl_requested, sasl_to_do, sasl_fail;
+ int i, length, num_caps_requested;
+
+ if (sasl)
+ {
+ sasl_requested = irc_server_sasl_enabled (server);
+ sasl_to_do = 0;
+ }
+ ptr_cap_option = IRC_SERVER_OPTION_STRING(
+ server,
+ IRC_SERVER_OPTION_CAPABILITIES);
+ length = ((ptr_cap_option && ptr_cap_option[0]) ?
+ strlen (ptr_cap_option) : 0) + 16;
+ cap_option = malloc (length);
+ cap_req = malloc (length);
+ if (cap_option && cap_req)
+ {
+ cap_option[0] = '\0';
+ if (ptr_cap_option && ptr_cap_option[0])
+ strcat (cap_option, ptr_cap_option);
+ if (sasl && sasl_requested)
+ {
+ if (cap_option[0])
+ strcat (cap_option, ",");
+ strcat (cap_option, "sasl");
+ }
+ cap_req[0] = '\0';
+ caps_requested = weechat_string_split (cap_option, ",", 0, 0,
+ &num_caps_requested);
+ if (caps_requested)
+ {
+ for (i = 0; i < num_caps_requested; i++)
+ {
+ if (weechat_hashtable_has_key (server->cap_ls,
+ caps_requested[i]) &&
+ !weechat_hashtable_has_key (server->cap_list,
+ caps_requested[i]))
+ {
+ if (sasl && strcmp (caps_requested[i], "sasl") == 0)
+ sasl_to_do = 1;
+ if (cap_req[0])
+ strcat (cap_req, " ");
+ strcat (cap_req, caps_requested[i]);
+ }
+ }
+ weechat_string_free_split (caps_requested);
+ }
+
+ if (cap_req[0])
+ {
+ weechat_printf (
+ server->buffer,
+ _("%s%s: client capability, requesting: %s"),
+ weechat_prefix ("network"), IRC_PLUGIN_NAME,
+ cap_req);
+ irc_server_sendf (server, 0, NULL,
+ "CAP REQ :%s", cap_req);
+ }
+
+ if (sasl)
+ {
+ if (!sasl_to_do)
+ irc_server_sendf (server, 0, NULL, "CAP END");
+ if (sasl_requested && !sasl_to_do)
+ {
+ weechat_printf (
+ server->buffer,
+ _("%s%s: client capability: SASL not supported"),
+ weechat_prefix ("network"), IRC_PLUGIN_NAME);
+
+ if (weechat_config_boolean (irc_config_network_sasl_fail_unavailable))
+ {
+ /* same handling as for sasl_end_fail */
+ sasl_fail = IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_SASL_FAIL);
+ if ((sasl_fail == IRC_SERVER_SASL_FAIL_RECONNECT)
+ || (sasl_fail == IRC_SERVER_SASL_FAIL_DISCONNECT))
+ {
+ irc_server_disconnect (
+ server, 0,
+ (sasl_fail == IRC_SERVER_SASL_FAIL_RECONNECT) ? 1 : 0);
+ }
+ }
+ }
+ }
+ }
+ if (cap_option)
+ free (cap_option);
+ if (cap_req)
+ free (cap_req);
+}
+
+/*
* Callback for the IRC message "CAP": client capability.
*
* Message looks like:
@@ -341,12 +485,12 @@ IRC_PROTOCOL_CALLBACK(away)
IRC_PROTOCOL_CALLBACK(cap)
{
- char *ptr_caps, **caps_supported, **caps_requested, **caps_added;
- char **caps_removed, *cap_option, *cap_req, str_msg_auth[512];
- const char *ptr_cap_option;
- int num_caps_supported, num_caps_requested, num_caps_added;
- int num_caps_removed, sasl_requested, sasl_to_do, sasl_mechanism;
- int sasl_fail, i, j, timeout, length;
+ char *ptr_caps, **caps_supported, **caps_added, **caps_removed;
+ char **caps_enabled, *pos_value, *str_name, *str_caps;
+ char str_msg_auth[512];
+ int num_caps_supported, num_caps_added, num_caps_removed;
+ int num_caps_enabled, sasl_to_do, sasl_mechanism;
+ int i, timeout, length, last_reply;
IRC_PROTOCOL_MIN_ARGS(4);
@@ -354,113 +498,168 @@ IRC_PROTOCOL_CALLBACK(cap)
{
if (argc > 4)
{
- ptr_caps = (argv_eol[4][0] == ':') ? argv_eol[4] + 1 : argv_eol[4];
- weechat_printf_date_tags (
- server->buffer, date, NULL,
- _("%s%s: client capability, server supports: %s"),
- weechat_prefix ("network"),
- IRC_PLUGIN_NAME,
- ptr_caps);
+ if (argc > 5 && (strcmp (argv[4], "*") == 0))
+ {
+ ptr_caps = argv_eol[5];
+ last_reply = 0;
+ }
+ else
+ {
+ ptr_caps = argv_eol[4];
+ last_reply = 1;
+ }
- /* auto-enable capabilities only when connecting to server */
- if (!server->is_connected)
+ if (!server->checking_cap_ls)
+ {
+ weechat_hashtable_remove_all (server->cap_ls);
+ server->checking_cap_ls = 1;
+ }
+
+ if (last_reply)
+ server->checking_cap_ls = 0;
+
+ if (ptr_caps[0] == ':')
+ ptr_caps++;
+
+ caps_supported = weechat_string_split (ptr_caps, " ", 0, 0,
+ &num_caps_supported);
+ if (caps_supported)
{
- sasl_requested = irc_server_sasl_enabled (server);
- sasl_to_do = 0;
- ptr_cap_option = IRC_SERVER_OPTION_STRING(
- server,
- IRC_SERVER_OPTION_CAPABILITIES);
- length = ((ptr_cap_option && ptr_cap_option[0]) ?
- strlen (ptr_cap_option) : 0) + 16;
- cap_option = malloc (length);
- cap_req = malloc (length);
- if (cap_option && cap_req)
+ for (i = 0; i < num_caps_supported; i++)
{
- cap_option[0] = '\0';
- if (ptr_cap_option && ptr_cap_option[0])
- strcat (cap_option, ptr_cap_option);
- if (sasl_requested)
- {
- if (cap_option[0])
- strcat (cap_option, ",");
- strcat (cap_option, "sasl");
- }
- cap_req[0] = '\0';
- caps_requested = weechat_string_split (cap_option, ",", 0, 0,
- &num_caps_requested);
- caps_supported = weechat_string_split (ptr_caps, " ", 0, 0,
- &num_caps_supported);
- if (caps_requested && caps_supported)
+ pos_value = strstr (caps_supported[i], "=");
+ if (pos_value)
{
- for (i = 0; i < num_caps_requested; i++)
+ str_name = strndup (caps_supported[i],
+ pos_value - caps_supported[i]);
+ if (str_name)
{
- for (j = 0; j < num_caps_supported; j++)
- {
- if (weechat_strcasecmp (caps_requested[i],
- caps_supported[j]) == 0)
- {
- if (strcmp (caps_requested[i], "sasl") == 0)
- sasl_to_do = 1;
- if (cap_req[0])
- strcat (cap_req, " ");
- strcat (cap_req, caps_supported[j]);
- }
- }
+ weechat_hashtable_set (server->cap_ls,
+ str_name, pos_value + 1);
+ free (str_name);
}
}
- if (caps_requested)
- weechat_string_free_split (caps_requested);
- if (caps_supported)
- weechat_string_free_split (caps_supported);
- if (cap_req[0])
+ else
{
- weechat_printf (
- server->buffer,
- _("%s%s: client capability, requesting: %s"),
- weechat_prefix ("network"), IRC_PLUGIN_NAME,
- cap_req);
- irc_server_sendf (server, 0, NULL,
- "CAP REQ :%s", cap_req);
+ weechat_hashtable_set (server->cap_ls,
+ caps_supported[i], NULL);
}
- if (!sasl_to_do)
- irc_server_sendf (server, 0, NULL, "CAP END");
- if (sasl_requested && !sasl_to_do)
- {
- weechat_printf (
- server->buffer,
- _("%s%s: client capability: SASL not supported"),
- weechat_prefix ("network"), IRC_PLUGIN_NAME);
+ }
+ }
- if (weechat_config_boolean (irc_config_network_sasl_fail_unavailable))
- {
- /* same handling as for sasl_end_fail */
- sasl_fail = IRC_SERVER_OPTION_INTEGER(server, IRC_SERVER_OPTION_SASL_FAIL);
- if ((sasl_fail == IRC_SERVER_SASL_FAIL_RECONNECT)
- || (sasl_fail == IRC_SERVER_SASL_FAIL_DISCONNECT))
- {
- irc_server_disconnect (
- server, 0,
- (sasl_fail == IRC_SERVER_SASL_FAIL_RECONNECT) ? 1 : 0);
- }
- }
- }
+ if (last_reply)
+ {
+ length = 0;
+ weechat_hashtable_map_string (server->cap_ls,
+ irc_protocol_cap_length_cb,
+ &length);
+
+ str_caps = malloc (length + 1);
+ if (str_caps)
+ {
+ str_caps[0] = '\0';
+ weechat_hashtable_map_string (server->cap_ls,
+ irc_protocol_cap_print_cb,
+ str_caps);
+
+ weechat_printf_date_tags (
+ server->buffer, date, NULL,
+ _("%s%s: client capability, server supports:%s"),
+ weechat_prefix ("network"),
+ IRC_PLUGIN_NAME,
+ str_caps);
+ free (str_caps);
}
- if (cap_option)
- free (cap_option);
- if (cap_req)
- free (cap_req);
}
+
+ /* auto-enable capabilities only when connecting to server */
+ if (last_reply && !server->is_connected)
+ irc_protocol_cap_sync (server, 1);
+
+ if (caps_supported)
+ weechat_string_free_split (caps_supported);
}
}
else if (strcmp (argv[3], "LIST") == 0)
{
if (argc > 4)
{
- ptr_caps = (argv_eol[4][0] == ':') ? argv_eol[4] + 1 : argv_eol[4];
- weechat_printf_date_tags (
- server->buffer, date, NULL,
- _("%s%s: client capability, currently enabled: %s"),
- weechat_prefix ("network"), IRC_PLUGIN_NAME, ptr_caps);
+ if (argc > 5 && (strcmp (argv[4], "*") == 0))
+ {
+ ptr_caps = argv_eol[5];
+ last_reply = 0;
+ }
+ else
+ {
+ ptr_caps = argv_eol[4];
+ last_reply = 1;
+ }
+
+ if (!server->checking_cap_list)
+ {
+ weechat_hashtable_remove_all (server->cap_list);
+ server->checking_cap_list = 1;
+ }
+
+ if (last_reply)
+ server->checking_cap_list = 0;
+
+ if (ptr_caps[0] == ':')
+ ptr_caps++;
+
+ caps_enabled = weechat_string_split (ptr_caps, " ", 0, 0,
+ &num_caps_enabled);
+ if (caps_enabled)
+ {
+ for (i = 0; i < num_caps_enabled; i++)
+ {
+ pos_value = strstr (caps_enabled[i], "=");
+ if (pos_value)
+ {
+ str_name = strndup (caps_enabled[i],
+ pos_value - caps_enabled[i]);
+ if (str_name)
+ {
+ weechat_hashtable_set (server->cap_list,
+ str_name, pos_value + 1);
+ free (str_name);
+ }
+ }
+ else
+ {
+ weechat_hashtable_set (server->cap_list,
+ caps_enabled[i], NULL);
+ }
+ }
+ }
+
+
+ if (last_reply)
+ {
+ length = 0;
+ weechat_hashtable_map_string (server->cap_list,
+ irc_protocol_cap_length_cb,
+ &length);
+
+ str_caps = malloc (length + 1);
+ if (str_caps)
+ {
+ str_caps[0] = '\0';
+ weechat_hashtable_map_string (server->cap_list,
+ irc_protocol_cap_print_cb,
+ str_caps);
+
+ weechat_printf_date_tags (
+ server->buffer, date, NULL,
+ _("%s%s: client capability, currently enabled:%s"),
+ weechat_prefix ("network"), IRC_PLUGIN_NAME, str_caps);
+ free (str_caps);
+ }
+ }
+
+
+ if (caps_enabled)
+ weechat_string_free_split (caps_enabled);
}
}
else if (strcmp (argv[3], "ACK") == 0)
@@ -479,23 +678,13 @@ IRC_PROTOCOL_CALLBACK(cap)
{
for (i = 0; i < num_caps_supported; i++)
{
+ weechat_hashtable_set (server->cap_list, caps_supported[i], NULL);
+
if (strcmp (caps_supported[i], "sasl") == 0)
{
sasl_to_do = 1;
break;
}
- else if (strcmp (caps_supported[i], "away-notify") == 0)
- {
- server->cap_away_notify = 1;
- }
- else if (strcmp (caps_supported[i], "account-notify") == 0)
- {
- server->cap_account_notify = 1;
- }
- else if (strcmp (caps_supported[i], "extended-join") == 0)
- {
- server->cap_extended_join = 1;
- }
}
weechat_string_free_split (caps_supported);
}
@@ -546,64 +735,37 @@ IRC_PROTOCOL_CALLBACK(cap)
server->buffer, date, NULL,
_("%s%s: client capability, now available: %s"),
weechat_prefix ("network"), IRC_PLUGIN_NAME, ptr_caps);
-
- /*
- * assume that we're not requesting any already-enabled
- * capabilities
- * TODO: SASL Reauthentication
- */
- ptr_cap_option = IRC_SERVER_OPTION_STRING(
- server,
- IRC_SERVER_OPTION_CAPABILITIES);
- length = ((ptr_cap_option && ptr_cap_option[0]) ?
- strlen (ptr_cap_option) : 0) + 16;
- cap_option = malloc (length);
- cap_req = malloc (length);
- if (cap_option && cap_req)
+ caps_added = weechat_string_split (ptr_caps, " ", 0, 0,
+ &num_caps_added);
+ if (caps_added)
{
- cap_option[0] = '\0';
- if (ptr_cap_option && ptr_cap_option[0])
- strcat (cap_option, ptr_cap_option);
- cap_req[0] = '\0';
- caps_requested = weechat_string_split (cap_option, ",", 0, 0,
- &num_caps_requested);
- caps_added = weechat_string_split (ptr_caps, " ", 0, 0,
- &num_caps_added);
- if (caps_requested && caps_added)
+ for (i = 0; i < num_caps_added; i++)
{
- for (i = 0; i < num_caps_requested; i++)
+ pos_value = strstr (caps_added[i], "=");
+ if (pos_value)
{
- for (j = 0; j < num_caps_added; j++)
+ str_name = strndup (caps_added[i],
+ pos_value - caps_added[i]);
+ if (str_name)
{
- if (weechat_strcasecmp (caps_requested[i],
- caps_added[j]) == 0)
- {
- if (cap_req[0])
- strcat (cap_req, " ");
- strcat (cap_req, caps_added[j]);
- }
+ weechat_hashtable_set (server->cap_ls,
+ str_name, pos_value + 1);
+ free (str_name);
}
}
+ else
+ {
+ weechat_hashtable_set (server->cap_ls,
+ caps_added[i], NULL);
+ }
}
- if (caps_requested)
- weechat_string_free_split (caps_requested);
- if (caps_added)
- weechat_string_free_split (caps_added);
- if (cap_req[0])
- {
- weechat_printf (
- server->buffer,
- _("%s%s: client capability, requesting: %s"),
- weechat_prefix ("network"), IRC_PLUGIN_NAME,
- cap_req);
- irc_server_sendf (server, 0, NULL,
- "CAP REQ :%s", cap_req);
- }
+ weechat_string_free_split (caps_added);
}
- if (cap_option)
- free (cap_option);
- if (cap_req)
- free (cap_req);
+
+ /*
+ * TODO: SASL Reauthentication
+ */
+ irc_protocol_cap_sync (server, 0);
}
}
else if (strcmp (argv[3], "DEL") == 0)
@@ -621,14 +783,8 @@ IRC_PROTOCOL_CALLBACK(cap)
{
for (i = 0; i < num_caps_removed; i++)
{
- if (strcmp (caps_removed[i], "away-notify") == 0)
- {
- server->cap_away_notify = 0;
- }
- else if (strcmp (caps_removed[i], "account-notify") == 0)
- {
- server->cap_account_notify = 0;
- }
+ weechat_hashtable_remove (server->cap_ls, caps_removed[i]);
+ weechat_hashtable_remove (server->cap_list, caps_removed[i]);
}
weechat_string_free_split (caps_removed);
}
@@ -4329,7 +4485,8 @@ IRC_PROTOCOL_CALLBACK(352)
{
if (ptr_nick->realname)
free (ptr_nick->realname);
- ptr_nick->realname = (pos_realname && server->cap_extended_join) ?
+ ptr_nick->realname = (pos_realname &&
+ weechat_hashtable_has_key (server->cap_list, "extended-join")) ?
strdup (pos_realname) : NULL;
}
@@ -4565,7 +4722,7 @@ IRC_PROTOCOL_CALLBACK(354)
if (ptr_nick->account)
free (ptr_nick->account);
ptr_nick->account = (ptr_channel && pos_account
- && server->cap_account_notify) ?
+ && weechat_hashtable_has_key (server->cap_list, "account-notify")) ?
strdup (pos_account) : NULL;
}
@@ -4575,7 +4732,7 @@ IRC_PROTOCOL_CALLBACK(354)
if (ptr_nick->realname)
free (ptr_nick->realname);
ptr_nick->realname = (ptr_channel && pos_realname
- && server->cap_extended_join) ?
+ && weechat_hashtable_has_key (server->cap_list, "extended-join")) ?
strdup (pos_realname) : NULL;
}
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index ae403360b..2e43afab5 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -1314,9 +1314,18 @@ irc_server_alloc (const char *name)
new_server->nick_alternate_number = -1;
new_server->nick = NULL;
new_server->nick_modes = NULL;
- new_server->cap_away_notify = 0;
- new_server->cap_account_notify = 0;
- new_server->cap_extended_join = 0;
+ new_server->checking_cap_ls = 0;
+ new_server->cap_ls = weechat_hashtable_new (32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL,
+ NULL);
+ new_server->checking_cap_list = 0;
+ new_server->cap_list = weechat_hashtable_new (32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL,
+ NULL);
new_server->isupport = NULL;
new_server->prefix_modes = NULL;
new_server->prefix_chars = NULL;
@@ -3350,7 +3359,7 @@ irc_server_timer_cb (const void *pointer, void *data, int remaining_calls)
/* check away (only if lag check was not done) */
away_check = IRC_SERVER_OPTION_INTEGER(
ptr_server, IRC_SERVER_OPTION_AWAY_CHECK);
- if (!ptr_server->cap_away_notify
+ if (!weechat_hashtable_has_key (ptr_server->cap_list, "away-notify")
&& (away_check > 0)
&& ((ptr_server->last_away_check == 0)
|| (current_time >= ptr_server->last_away_check + (away_check * 60))))
@@ -3669,7 +3678,7 @@ irc_server_login (struct t_irc_server *server)
if (irc_server_sasl_enabled (server) || (capabilities && capabilities[0]))
{
- irc_server_sendf (server, 0, NULL, "CAP LS");
+ irc_server_sendf (server, 0, NULL, "CAP LS " IRC_SERVER_VERSION_CAP);
}
username2 = (username && username[0]) ?
@@ -5027,9 +5036,10 @@ irc_server_disconnect (struct t_irc_server *server, int switch_address,
weechat_bar_item_update ("input_prompt");
weechat_bar_item_update ("irc_nick_modes");
}
- server->cap_away_notify = 0;
- server->cap_account_notify = 0;
- server->cap_extended_join = 0;
+ server->checking_cap_ls = 0;
+ weechat_hashtable_remove_all (server->cap_ls);
+ server->checking_cap_list = 0;
+ weechat_hashtable_remove_all (server->cap_list);
server->is_away = 0;
server->away_time = 0;
server->lag = 0;
@@ -5578,9 +5588,10 @@ irc_server_hdata_server_cb (const void *pointer, void *data,
WEECHAT_HDATA_VAR(struct t_irc_server, nick_alternate_number, INTEGER, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, nick, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, nick_modes, STRING, 0, NULL, NULL);
- WEECHAT_HDATA_VAR(struct t_irc_server, cap_away_notify, INTEGER, 0, NULL, NULL);
- WEECHAT_HDATA_VAR(struct t_irc_server, cap_account_notify, INTEGER, 0, NULL, NULL);
- WEECHAT_HDATA_VAR(struct t_irc_server, cap_extended_join, INTEGER, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, checking_cap_ls, INTEGER, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, cap_ls, HASHTABLE, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, checking_cap_list, INTEGER, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, cap_list, HASHTABLE, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, isupport, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, prefix_modes, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, prefix_chars, STRING, 0, NULL, NULL);
@@ -5802,11 +5813,13 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "nick_modes", server->nick_modes))
return 0;
- if (!weechat_infolist_new_var_integer (ptr_item, "cap_away_notify", server->cap_away_notify))
+ if (!weechat_infolist_new_var_integer (ptr_item, "checking_cap_ls", server->checking_cap_ls))
return 0;
- if (!weechat_infolist_new_var_integer (ptr_item, "cap_account_notify", server->cap_account_notify))
+ if (!weechat_hashtable_add_to_infolist (server->cap_ls, ptr_item, "cap_ls"))
return 0;
- if (!weechat_infolist_new_var_integer (ptr_item, "cap_extended_join", server->cap_extended_join))
+ if (!weechat_infolist_new_var_integer (ptr_item, "checking_cap_list", server->checking_cap_list))
+ return 0;
+ if (!weechat_hashtable_add_to_infolist (server->cap_list, ptr_item, "cap_list"))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "isupport", server->isupport))
return 0;
@@ -6186,9 +6199,14 @@ irc_server_print_log ()
weechat_log_printf (" nick_alternate_number: %d", ptr_server->nick_alternate_number);
weechat_log_printf (" nick . . . . . . . . : '%s'", ptr_server->nick);
weechat_log_printf (" nick_modes . . . . . : '%s'", ptr_server->nick_modes);
- weechat_log_printf (" cap_away_notify. . . : %d", ptr_server->cap_away_notify);
- weechat_log_printf (" cap_account_notify . : %d", ptr_server->cap_account_notify);
- weechat_log_printf (" cap_extended_join. . : %d", ptr_server->cap_extended_join);
+ weechat_log_printf (" checking_cap_ls. . . : %d", ptr_server->checking_cap_ls);
+ weechat_log_printf (" cap_ls . . . . . . . : 0x%lx (hashtable: '%s')",
+ ptr_server->cap_ls,
+ weechat_hashtable_get_string (ptr_server->cap_ls, "keys_values"));
+ weechat_log_printf (" checking_cap_list. . : %d", ptr_server->checking_cap_list);
+ weechat_log_printf (" cap_list . . . . . . : 0x%lx (hashtable: '%s')",
+ ptr_server->cap_list,
+ weechat_hashtable_get_string (ptr_server->cap_list, "keys_values"));
weechat_log_printf (" isupport . . . . . . : '%s'", ptr_server->isupport);
weechat_log_printf (" prefix_modes . . . . : '%s'", ptr_server->prefix_modes);
weechat_log_printf (" prefix_chars . . . . : '%s'", ptr_server->prefix_chars);
diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h
index 84b64ca6d..401f627bb 100644
--- a/src/plugins/irc/irc-server.h
+++ b/src/plugins/irc/irc-server.h
@@ -122,6 +122,9 @@ enum t_irc_server_option
#define IRC_SERVER_SEND_OUTQ_PRIO_LOW 2
#define IRC_SERVER_SEND_RETURN_HASHTABLE 4
+/* version strings */
+#define IRC_SERVER_VERSION_CAP "302"
+
/* casemapping (string comparisons for nicks/channels) */
enum t_irc_server_casemapping
{
@@ -189,9 +192,10 @@ struct t_irc_server
/* (nick____1, nick____2, ...) */
char *nick; /* current nickname */
char *nick_modes; /* nick modes */
- int cap_away_notify; /* 1 if capability away-notify is enabled*/
- int cap_account_notify; /* 1 if CAP account-notify is enabled */
- int cap_extended_join; /* 1 if CAP extended-join is enabled */
+ int checking_cap_ls; /* 1 if checking supported capabilities */
+ struct t_hashtable *cap_ls; /* list of supported capabilities */
+ int checking_cap_list; /* 1 if checking enabled capabilities */
+ struct t_hashtable *cap_list; /* list of enabled capabilities */
char *isupport; /* copy of message 005 (ISUPPORT) */
char *prefix_modes; /* prefix modes from msg 005 (eg "ohv") */
char *prefix_chars; /* prefix chars from msg 005 (eg "@%+") */
diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c
index b8dcb0696..107981609 100644
--- a/src/plugins/irc/irc-upgrade.c
+++ b/src/plugins/irc/irc-upgrade.c
@@ -420,9 +420,27 @@ irc_upgrade_read_cb (const void *pointer, void *data,
str = weechat_infolist_string (infolist, "nick_modes");
if (str)
irc_upgrade_current_server->nick_modes = strdup (str);
- irc_upgrade_current_server->cap_away_notify = weechat_infolist_integer (infolist, "cap_away_notify");
- irc_upgrade_current_server->cap_account_notify = weechat_infolist_integer (infolist, "cap_account_notify");
- irc_upgrade_current_server->cap_extended_join = weechat_infolist_integer (infolist, "cap_extended_join");
+ /* "cap_ls" and "cap_list" replace "cap_away_notify" and "cap_account_notify" in WeeChat x.y.z */
+ if (weechat_infolist_integer (infolist, "cap_away_notify"))
+ {
+ weechat_hashtable_set (irc_upgrade_current_server->cap_ls, "away-notify", NULL);
+ weechat_hashtable_set (irc_upgrade_current_server->cap_list, "away-notify", NULL);
+ }
+ if (weechat_infolist_integer (infolist, "cap_account_notify"))
+ {
+ weechat_hashtable_set (irc_upgrade_current_server->cap_ls, "account-notify", NULL);
+ weechat_hashtable_set (irc_upgrade_current_server->cap_list, "account-notify", NULL);
+ }
+ if (weechat_infolist_integer (infolist, "cap_extended_join"))
+ {
+ weechat_hashtable_set (irc_upgrade_current_server->cap_ls, "extended-join", NULL);
+ weechat_hashtable_set (irc_upgrade_current_server->cap_list, "extended-join", NULL);
+ }
+ weechat_hashtable_add_from_infolist (
+ irc_upgrade_current_server->cap_ls, infolist, "cap_ls");
+ weechat_hashtable_add_from_infolist (
+ irc_upgrade_current_server->cap_list, infolist, "cap_list");
+
str = weechat_infolist_string (infolist, "isupport");
if (str)
irc_upgrade_current_server->isupport = strdup (str);
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 57bdf4103..0a49aa4e3 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -715,6 +715,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv)
new_plugin->hashtable_get_string = &hashtable_get_string;
new_plugin->hashtable_set_pointer = &hashtable_set_pointer;
new_plugin->hashtable_add_to_infolist = &hashtable_add_to_infolist;
+ new_plugin->hashtable_add_from_infolist = &hashtable_add_from_infolist;
new_plugin->hashtable_remove = &hashtable_remove;
new_plugin->hashtable_remove_all = &hashtable_remove_all;
new_plugin->hashtable_free = &hashtable_free;
diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h
index 02dc525ce..f9a836065 100644
--- a/src/plugins/weechat-plugin.h
+++ b/src/plugins/weechat-plugin.h
@@ -67,7 +67,7 @@ struct timeval;
* please change the date with current one; for a second change at same
* date, increment the 01, otherwise please keep 01.
*/
-#define WEECHAT_PLUGIN_API_VERSION "20171223-01"
+#define WEECHAT_PLUGIN_API_VERSION "20180520-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -468,6 +468,9 @@ struct t_weechat_plugin
int (*hashtable_add_to_infolist) (struct t_hashtable *hashtable,
struct t_infolist_item *infolist_item,
const char *prefix);
+ int (*hashtable_add_from_infolist) (struct t_hashtable *hashtable,
+ struct t_infolist *infolist,
+ const char *prefix);
void (*hashtable_remove) (struct t_hashtable *hashtable, const void *key);
void (*hashtable_remove_all) (struct t_hashtable *hashtable);
void (*hashtable_free) (struct t_hashtable *hashtable);
@@ -1401,6 +1404,11 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
(weechat_plugin->hashtable_add_to_infolist)(__hashtable, \
__infolist_item, \
__prefix)
+#define weechat_hashtable_add_from_infolist(__hashtable, __infolist, \
+ __prefix) \
+ (weechat_plugin->hashtable_add_from_infolist)(__hashtable, \
+ __infolist, \
+ __prefix)
#define weechat_hashtable_remove(__hashtable, __key) \
(weechat_plugin->hashtable_remove)(__hashtable, __key)
#define weechat_hashtable_remove_all(__hashtable) \