diff options
-rw-r--r-- | src/plugins/irc/irc-protocol.c | 5 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 40 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.h | 1 | ||||
-rw-r--r-- | src/plugins/irc/irc-upgrade.c | 14 | ||||
-rw-r--r-- | tests/unit/plugins/irc/test-irc-protocol.cpp | 8 |
5 files changed, 50 insertions, 18 deletions
diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c index 73424482a..c22fe28af 100644 --- a/src/plugins/irc/irc-protocol.c +++ b/src/plugins/irc/irc-protocol.c @@ -4004,6 +4004,11 @@ IRC_PROTOCOL_CALLBACK(005) if (utf8mapping >= 0) server->utf8mapping = utf8mapping; } + else if (strcmp (params[i], "UTF8ONLY") == 0) + { + /* save utf8only */ + server->utf8only = 1; + } else if (strncmp (params[i], "CHANTYPES=", 10) == 0) { /* save chantypes */ diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index a608a287b..0166e4a9e 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -1715,6 +1715,7 @@ irc_server_alloc (const char *name) new_server->host_max_length = 0; new_server->casemapping = IRC_SERVER_CASEMAPPING_RFC1459; new_server->utf8mapping = IRC_SERVER_UTF8MAPPING_NONE; + new_server->utf8only = 0; new_server->chantypes = NULL; new_server->chanmodes = NULL; new_server->monitor = 0; @@ -2955,17 +2956,14 @@ irc_server_send_one_msg (struct t_irc_server *server, int flags, server->name); } - - if (!irc_server_get_isupport_value (server, "UTF8ONLY")) + /* + * when UTF8ONLY is enabled, clients must not send non-UTF-8 data + * to the server; the charset encoding below is then done only if + * UTF8ONLY is *NOT* enabled + * (see: https://ircv3.net/specs/extensions/utf8-only) + */ + if (!server->utf8only) { - /* "Clients implementing this specification MUST NOT send - * non-UTF-8 data to the server once they have seen - * this token." - * "If a client implementing this specification sees this token, - * they MUST set their outgoing encoding to UTF-8 without - * requiring any user intervention." - * -- https://ircv3.net/specs/extensions/utf8-only - */ msg_encoded = irc_message_convert_charset (ptr_msg, pos_encode, "charset_encode", modifier_data); @@ -3562,14 +3560,17 @@ irc_server_msgq_flush () irc_recv_msgq->server->name); } } - if (!irc_server_get_isupport_value (irc_recv_msgq->server, - "UTF8ONLY")) + + /* + * when UTF8ONLY is enabled, servers must + * not relay content containing non-UTF-8 + * data to clients; the charset decoding below + * is then done only if UTF8ONLY is *NOT* + * enabled + * (see: https://ircv3.net/specs/extensions/utf8-only) + */ + if (!irc_recv_msgq->server->utf8only) { - /* "Servers publishing this token MUST NOT relay content - * [...] containing non-UTF-8 data to clients" - * -- https://ircv3.net/specs/extensions/utf8-only - * Therefore, no need to decode, we are sure it is UTF-8. - */ msg_decoded = irc_message_convert_charset ( ptr_msg, pos_decode, "charset_decode", modifier_data); @@ -5718,6 +5719,7 @@ irc_server_disconnect (struct t_irc_server *server, int switch_address, server->host_max_length = 0; server->casemapping = IRC_SERVER_CASEMAPPING_RFC1459; server->utf8mapping = IRC_SERVER_UTF8MAPPING_NONE; + server->utf8only = 0; if (server->chantypes) { free (server->chantypes); @@ -6418,6 +6420,7 @@ irc_server_hdata_server_cb (const void *pointer, void *data, WEECHAT_HDATA_VAR(struct t_irc_server, host_max_length, INTEGER, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_server, casemapping, INTEGER, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_server, utf8mapping, INTEGER, 0, NULL, NULL); + WEECHAT_HDATA_VAR(struct t_irc_server, utf8only, INTEGER, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_server, chantypes, STRING, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_server, chanmodes, STRING, 0, NULL, NULL); WEECHAT_HDATA_VAR(struct t_irc_server, monitor, INTEGER, 0, NULL, NULL); @@ -6800,6 +6803,8 @@ irc_server_add_to_infolist (struct t_infolist *infolist, return 0; if (!weechat_infolist_new_var_string (ptr_item, "utf8mapping_string", irc_server_utf8mapping_string[server->utf8mapping])) return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "utf8only", server->utf8only)) + return 0; if (!weechat_infolist_new_var_string (ptr_item, "chantypes", server->chantypes)) return 0; if (!weechat_infolist_new_var_string (ptr_item, "chanmodes", server->chanmodes)) @@ -7193,6 +7198,7 @@ irc_server_print_log () weechat_log_printf (" utf8mapping . . . . . . . : %d (%s)", ptr_server->utf8mapping, irc_server_utf8mapping_string[ptr_server->utf8mapping]); + weechat_log_printf (" utf8only. . . . . . . . . : %d", ptr_server->utf8only); weechat_log_printf (" chantypes . . . . . . . . : '%s'", ptr_server->chantypes); weechat_log_printf (" chanmodes . . . . . . . . : '%s'", ptr_server->chanmodes); weechat_log_printf (" monitor . . . . . . . . . : %d", ptr_server->monitor); diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index 3c3a574c9..cbfb05d82 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -248,6 +248,7 @@ struct t_irc_server int host_max_length; /* max length of host (from msg 005) */ int casemapping; /* casemapping from msg 005 */ int utf8mapping; /* utf8mapping from msg 005 */ + int utf8only; /* UTF-8 only? */ char *chantypes; /* chantypes from msg 005 (eg "&#") */ char *chanmodes; /* chanmodes from msg 005 */ /* (eg "beI,k,l,imnpstaqr") */ diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c index 231eb8805..b717418ca 100644 --- a/src/plugins/irc/irc-upgrade.c +++ b/src/plugins/irc/irc-upgrade.c @@ -557,6 +557,20 @@ irc_upgrade_read_cb (const void *pointer, void *data, irc_upgrade_current_server->utf8mapping = utf8mapping; } } + /* "utf8only" is new in WeeChat 4.0.0 */ + if (weechat_infolist_search_var (infolist, "utf8only")) + { + irc_upgrade_current_server->utf8only = weechat_infolist_integer (infolist, "utf8only"); + } + else + { + /* WeeChat <= 3.8 */ + irc_upgrade_current_server->utf8only = ( + irc_server_get_isupport_value ( + irc_upgrade_current_server, + "UTF8ONLY")) ? + 1 : 0; + } str = weechat_infolist_string (infolist, "chantypes"); if (str) irc_upgrade_current_server->chantypes = strdup (str); diff --git a/tests/unit/plugins/irc/test-irc-protocol.cpp b/tests/unit/plugins/irc/test-irc-protocol.cpp index c99ef13bb..97d6ebb25 100644 --- a/tests/unit/plugins/irc/test-irc-protocol.cpp +++ b/tests/unit/plugins/irc/test-irc-protocol.cpp @@ -65,7 +65,7 @@ extern char *irc_protocol_cap_to_enable (const char *capabilities, "CASEMAPPING=strict-rfc1459 LINELEN=4096 NICKLEN=30 MAXNICKLEN=31 " \ "USERLEN=16 HOSTLEN=32 CHANNELLEN=50 TOPICLEN=390 DEAF=D " \ "CHANTYPES=# CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz " \ - "MONITOR=100" + "MONITOR=100 UTF8MAPPING=rfc8265 UTF8ONLY" #define IRC_ALL_CAPS "account-notify,away-notify,batch,cap-notify," \ "chghost,draft/multiline,extended-join,invite-notify,message-tags," \ "multi-prefix,server-time,setname,userhost-in-names" @@ -2447,6 +2447,8 @@ TEST(IrcProtocolWithServer, 005_full) POINTERS_EQUAL(NULL, ptr_server->chantypes); POINTERS_EQUAL(NULL, ptr_server->chanmodes); LONGS_EQUAL(0, ptr_server->monitor); + LONGS_EQUAL(IRC_SERVER_UTF8MAPPING_NONE, ptr_server->utf8mapping); + LONGS_EQUAL(0, ptr_server->utf8only); POINTERS_EQUAL(NULL, ptr_server->isupport); RECV(":server 005 alice " IRC_MSG_005 " :are supported"); @@ -2462,6 +2464,8 @@ TEST(IrcProtocolWithServer, 005_full) STRCMP_EQUAL("#", ptr_server->chantypes); STRCMP_EQUAL("eIbq,k,flj,CFLMPQScgimnprstuz", ptr_server->chanmodes); LONGS_EQUAL(100, ptr_server->monitor); + LONGS_EQUAL(IRC_SERVER_UTF8MAPPING_RFC8265, ptr_server->utf8mapping); + LONGS_EQUAL(1, ptr_server->utf8only); STRCMP_EQUAL(IRC_MSG_005, ptr_server->isupport); /* check that realloc of info is OK if we receive the message again */ @@ -2478,6 +2482,8 @@ TEST(IrcProtocolWithServer, 005_full) STRCMP_EQUAL("#", ptr_server->chantypes); STRCMP_EQUAL("eIbq,k,flj,CFLMPQScgimnprstuz", ptr_server->chanmodes); LONGS_EQUAL(100, ptr_server->monitor); + LONGS_EQUAL(IRC_SERVER_UTF8MAPPING_RFC8265, ptr_server->utf8mapping); + LONGS_EQUAL(1, ptr_server->utf8only); STRCMP_EQUAL(IRC_MSG_005 " " IRC_MSG_005, ptr_server->isupport); } |