1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-30 06:46:38 +02:00

irc: add missing tags on multiline messages (issue #1987)

This commit is contained in:
Sébastien Helleu
2023-08-09 14:53:03 +02:00
parent 7c0b16df81
commit bc5b287622
10 changed files with 338 additions and 27 deletions
+7
View File
@@ -10,6 +10,13 @@ This document lists all the changes for each version. +
For a list of important changes that require manual actions, please look at release notes.
[[v4.0.4]]
== Version 4.0.4 (under dev)
Bug fixes::
* irc: add missing tags on multiline messages (issue #1987)
[[v4.0.3]]
== Version 4.0.3 (2023-08-08)
+5
View File
@@ -11,6 +11,11 @@ It is recommended to read it when upgrading to a new stable version. +
For a complete list of changes, please look at ChangeLog.
[[v4.0.4]]
== Version 4.0.4 (under dev)
No release notes.
[[v4.0.3]]
== Version 4.0.3 (2023-08-08)
+19 -7
View File
@@ -110,7 +110,7 @@ irc_batch_add_to_list (struct t_irc_server *server, struct t_irc_batch *batch)
struct t_irc_batch *
irc_batch_start_batch (struct t_irc_server *server, const char *reference,
const char *parent_ref, const char *type,
const char *parameters)
const char *parameters, struct t_hashtable *tags)
{
struct t_irc_batch *ptr_batch;
@@ -130,6 +130,7 @@ irc_batch_start_batch (struct t_irc_server *server, const char *reference,
ptr_batch->parent_ref = (parent_ref) ? strdup (parent_ref) : NULL;
ptr_batch->type = strdup (type);
ptr_batch->parameters = (parameters) ? strdup (parameters) : NULL;
ptr_batch->tags = (tags) ? weechat_hashtable_dup (tags) : NULL;
ptr_batch->start_time = time (NULL);
ptr_batch->messages = NULL;
ptr_batch->end_received = 0;
@@ -188,6 +189,8 @@ irc_batch_free (struct t_irc_server *server, struct t_irc_batch *batch)
free (batch->type);
if (batch->parameters)
free (batch->parameters);
if (batch->tags)
weechat_hashtable_free (batch->tags);
if (batch->messages)
weechat_string_dyn_free (batch->messages, 1);
@@ -226,7 +229,7 @@ irc_batch_process_messages (struct t_irc_server *server,
struct t_irc_batch *batch)
{
char **list_messages, *command, *channel, modifier_data[1024], *new_messages;
char *message;
char *message, *message2;
int i, count_messages;
if (!batch || !batch->messages)
@@ -261,8 +264,13 @@ irc_batch_process_messages (struct t_irc_server *server,
if (!message)
continue;
message2 = irc_tag_add_tags_to_message (message,
batch->tags);
if (!message2)
continue;
irc_message_parse (server,
message,
message2,
NULL, /* tags */
NULL, /* message_without_tags */
NULL, /* nick */
@@ -280,13 +288,13 @@ irc_batch_process_messages (struct t_irc_server *server,
NULL); /* pos_text */
/* add raw message */
irc_raw_print (server, IRC_RAW_FLAG_RECV, message);
irc_raw_print (server, IRC_RAW_FLAG_RECV, message2);
/* call receive callback, ignoring batch tags */
irc_protocol_recv_command (server, message, command, channel, 1);
irc_protocol_recv_command (server, message2, command, channel, 1);
if (message)
free (message);
free (message);
free (message2);
if (command)
free (command);
if (channel)
@@ -562,6 +570,10 @@ irc_batch_print_log (struct t_irc_server *server)
weechat_log_printf (" parent_ref. . . . . : '%s'", ptr_batch->parent_ref);
weechat_log_printf (" type. . . . . . . . : '%s'", ptr_batch->type);
weechat_log_printf (" parameters. . . . . : '%s'", ptr_batch->parameters);
weechat_log_printf (" tags. . . . . . . . : 0x%lx (hashtable: '%s')",
ptr_batch->tags,
weechat_hashtable_get_string (ptr_batch->tags,
"keys_values"));
weechat_log_printf (" start_time. . . . . : %lld", (long long)ptr_batch->start_time);
weechat_log_printf (" message . . . . . . : 0x%lx ('%s')",
ptr_batch->messages,
+4 -1
View File
@@ -22,6 +22,7 @@
#include <time.h>
struct t_hashtable;
struct t_irc_server;
struct t_irc_batch
@@ -30,6 +31,7 @@ struct t_irc_batch
char *parent_ref; /* ref of parent batch (optional) */
char *type; /* type */
char *parameters; /* parameters */
struct t_hashtable *tags; /* batch message tags */
time_t start_time; /* start time (to auto-purge if */
/* batch end is not received) */
char **messages; /* messages separated by '\n' */
@@ -46,7 +48,8 @@ extern struct t_irc_batch *irc_batch_start_batch (struct t_irc_server *server,
const char *reference,
const char *parent_ref,
const char *type,
const char *parameters);
const char *parameters,
struct t_hashtable *tags);
extern int irc_batch_add_message (struct t_irc_server *server,
const char *reference,
const char *irc_message);
+2 -1
View File
@@ -688,7 +688,8 @@ IRC_PROTOCOL_CALLBACK(batch)
params[0] + 1, /* reference */
weechat_hashtable_get (tags, "batch"), /* parent ref */
params[1], /* type */
str_params);
str_params,
tags);
if (str_params)
free (str_params);
}
+156
View File
@@ -283,3 +283,159 @@ irc_tag_parse (const char *tags,
return num_tags;
}
/*
* Adds tags to a dynamic string, separated by semicolons, with escaped
* tag values.
*/
void
irc_tag_add_to_string_cb (void *data,
struct t_hashtable *hashtable,
const void *key,
const void *value)
{
char **string, *escaped;
/* make C compiler happy */
(void) hashtable;
string = (char **)data;
if (*string[0])
weechat_string_dyn_concat (string, ";", -1);
weechat_string_dyn_concat (string, key, -1);
if (value)
{
weechat_string_dyn_concat (string, "=", -1);
escaped = irc_tag_escape_value ((const char *)value);
weechat_string_dyn_concat (string,
(escaped) ? escaped : (const char *)value,
-1);
if (escaped)
free (escaped);
}
}
/*
* Converts hashtable with tags to a string (tags and values are escaped).
*
* Note: result must be freed after use.
*/
char *
irc_tag_hashtable_to_string (struct t_hashtable *tags)
{
char **string;
if (!tags)
return NULL;
string = weechat_string_dyn_alloc (64);
if (!string)
return NULL;
weechat_hashtable_map (tags, &irc_tag_add_to_string_cb, string);
return weechat_string_dyn_free (string, 0);
}
/*
* Adds tags to another hashtable.
*/
void
irc_tag_add_to_hashtable_cb (void *data,
struct t_hashtable *hashtable,
const void *key,
const void *value)
{
/* make C compiler happy */
(void) hashtable;
if (!weechat_hashtable_has_key ((struct t_hashtable *)data, key))
weechat_hashtable_set ((struct t_hashtable *)data, key, value);
}
/*
* Adds tags to an IRC message.
* Existing tags in message are kept unchanged.
*
* Note: result must be freed after use.
*/
char *
irc_tag_add_tags_to_message (const char *message, struct t_hashtable *tags)
{
char *msg_str_tags, **result, *new_tags;
const char *pos_space, *ptr_message;
struct t_hashtable *msg_hash_tags;
if (!message)
return NULL;
if (!tags)
return strdup (message);
result = NULL;
msg_str_tags = NULL;
msg_hash_tags = NULL;
new_tags = NULL;
if (message[0] == '@')
{
pos_space = strchr (message, ' ');
if (!pos_space)
goto end;
msg_str_tags = weechat_strndup (message + 1, pos_space - message - 1);
ptr_message = pos_space + 1;
while (ptr_message[0] == ' ')
{
ptr_message++;
}
}
else
{
ptr_message = message;
}
msg_hash_tags = weechat_hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL, NULL);
if (!msg_hash_tags)
goto end;
if (msg_str_tags)
irc_tag_parse (msg_str_tags, msg_hash_tags, NULL);
weechat_hashtable_map (tags, &irc_tag_add_to_hashtable_cb, msg_hash_tags);
result = weechat_string_dyn_alloc (64);
if (!result)
goto end;
new_tags = irc_tag_hashtable_to_string (msg_hash_tags);
if (!new_tags)
goto end;
if (new_tags[0])
{
weechat_string_dyn_concat (result, "@", -1);
weechat_string_dyn_concat (result, new_tags, -1);
weechat_string_dyn_concat (result, " ", -1);
}
weechat_string_dyn_concat (result, ptr_message, -1);
end:
if (msg_str_tags)
free (msg_str_tags);
if (msg_hash_tags)
weechat_hashtable_free (msg_hash_tags);
if (new_tags)
free (new_tags);
return (result) ? weechat_string_dyn_free (result, 0) : NULL;
}
+2
View File
@@ -30,5 +30,7 @@ extern char *irc_tag_modifier_cb (const void *pointer,
extern int irc_tag_parse (const char *tags,
struct t_hashtable *hashtable,
const char *prefix_key);
extern char *irc_tag_add_tags_to_message (const char *message,
struct t_hashtable *tags);
#endif /* WEECHAT_PLUGIN_IRC_TAG_H */
+37 -7
View File
@@ -26,6 +26,8 @@
extern "C"
{
#include <string.h>
#include "src/core/wee-hashtable.h"
#include "src/plugins/weechat-plugin.h"
#include "src/plugins/irc/irc-batch.h"
#include "src/plugins/irc/irc-server.h"
}
@@ -43,14 +45,23 @@ TEST(IrcBatch, Search)
{
struct t_irc_server *server;
struct t_irc_batch *batch1, *batch2;
struct t_hashtable *tags;
server = irc_server_alloc ("server");
CHECK(server);
batch1 = irc_batch_start_batch (server, "ref1", "parent_ref", "type", "params");
tags = hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL, NULL);
CHECK(tags);
hashtable_set (tags, "time", "2023-08-09T07:43:01.830Z");
hashtable_set (tags, "msgid", "icqfzy7zdbpix4gy8pvzuv49kw");
batch1 = irc_batch_start_batch (server, "ref1", "parent_ref", "type", "params", tags);
CHECK(batch1);
batch2 = irc_batch_start_batch (server, "ref2", "parent_ref", "type", "params");
batch2 = irc_batch_start_batch (server, "ref2", "parent_ref", "type", "params", NULL);
CHECK(batch2);
POINTERS_EQUAL(NULL, irc_batch_search (NULL, NULL));
@@ -105,19 +116,29 @@ TEST(IrcBatch, StartBatch)
{
struct t_irc_server *server;
struct t_irc_batch *batch;
struct t_hashtable *tags;
server = irc_server_alloc ("server");
CHECK(server);
tags = hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL, NULL);
CHECK(tags);
hashtable_set (tags, "time", "2023-08-09T07:43:01.830Z");
hashtable_set (tags, "msgid", "icqfzy7zdbpix4gy8pvzuv49kw");
POINTERS_EQUAL(NULL, server->batches);
batch = irc_batch_start_batch (server, "ref", NULL, "type", NULL);
batch = irc_batch_start_batch (server, "ref", NULL, "type", NULL, NULL);
CHECK(batch);
POINTERS_EQUAL(batch, server->batches);
STRCMP_EQUAL("ref", batch->reference);
POINTERS_EQUAL(NULL, batch->parent_ref);
STRCMP_EQUAL("type", batch->type);
POINTERS_EQUAL(NULL, batch->parameters);
POINTERS_EQUAL(NULL, batch->tags);
CHECK(batch->start_time > 0);
POINTERS_EQUAL(NULL, batch->messages);
LONGS_EQUAL(0, batch->end_received);
@@ -126,13 +147,19 @@ TEST(IrcBatch, StartBatch)
POINTERS_EQUAL(NULL, server->batches);
batch = irc_batch_start_batch (server, "ref", "parent_ref", "type", "params");
batch = irc_batch_start_batch (server, "ref", "parent_ref", "type", "params",
tags);
CHECK(batch);
POINTERS_EQUAL(batch, server->batches);
STRCMP_EQUAL("ref", batch->reference);
STRCMP_EQUAL("parent_ref", batch->parent_ref);
STRCMP_EQUAL("type", batch->type);
STRCMP_EQUAL("params", batch->parameters);
CHECK(batch->tags);
STRCMP_EQUAL("2023-08-09T07:43:01.830Z",
(const char *)hashtable_get (batch->tags, "time"));
STRCMP_EQUAL("icqfzy7zdbpix4gy8pvzuv49kw",
(const char *)hashtable_get (batch->tags, "msgid"));
CHECK(batch->start_time > 0);
POINTERS_EQUAL(NULL, batch->messages);
@@ -159,7 +186,8 @@ TEST(IrcBatch, AddMessage)
server = irc_server_alloc ("server");
CHECK(server);
batch = irc_batch_start_batch (server, "ref", "parent_ref", "type", "params");
batch = irc_batch_start_batch (server, "ref", "parent_ref", "type", "params",
NULL);
CHECK(batch);
irc_batch_add_message (server, "ref", ":alice PRIVMSG #test: test1");
@@ -187,10 +215,12 @@ TEST(IrcBatch, FreeAll)
server = irc_server_alloc ("server");
CHECK(server);
batch1 = irc_batch_start_batch (server, "ref1", "parent_ref", "type", "params");
batch1 = irc_batch_start_batch (server, "ref1", "parent_ref", "type", "params",
NULL);
CHECK(batch1);
batch2 = irc_batch_start_batch (server, "ref2", "parent_ref", "type", "params");
batch2 = irc_batch_start_batch (server, "ref2", "parent_ref", "type", "params",
NULL);
CHECK(batch2);
POINTERS_EQUAL(batch1, server->batches);
+15 -11
View File
@@ -1625,7 +1625,8 @@ TEST(IrcProtocolWithServer, batch_with_batch_cap)
POINTERS_EQUAL(NULL, irc_batch_search (ptr_server, "ref2"));
/* multiline */
RECV(":server BATCH +ref draft/multiline #test");
RECV("@time=2023-08-09T07:43:01.830Z;msgid=icqfzy7zdbpix4gy8pvzuv49kw "
":server BATCH +ref draft/multiline #test");
CHECK_NO_MSG;
RECV("@batch=ref :bob!user_b@host_b PRIVMSG #test :line 1");
CHECK_NO_MSG;
@@ -1633,13 +1634,14 @@ TEST(IrcProtocolWithServer, batch_with_batch_cap)
CHECK_NO_MSG;
RECV(":server BATCH -ref");
CHECK_CHAN("bob", "line 1",
"irc_privmsg,irc_tag_batch=ref,irc_batch_type_draft/multiline,"
"notify_message,prefix_nick_248,nick_bob,"
"host_user_b@host_b,log1");
"irc_privmsg,irc_tag_batch=ref,irc_tag_time=2023-08-09T07:43:01.830Z,"
"irc_tag_msgid=icqfzy7zdbpix4gy8pvzuv49kw,"
"irc_batch_type_draft/multiline,notify_message,prefix_nick_248,"
"nick_bob,host_user_b@host_b,log1");
CHECK_CHAN("bob", "line 2",
"irc_privmsg,irc_tag_batch=ref,irc_batch_type_draft/multiline,"
"notify_message,prefix_nick_248,nick_bob,"
"host_user_b@host_b,log1");
"irc_privmsg,irc_tag_batch=ref,irc_tag_time=2023-08-09T07:43:01.830Z,"
"irc_tag_msgid=icqfzy7zdbpix4gy8pvzuv49kw,irc_batch_type_draft/multiline,"
"notify_message,prefix_nick_248,nick_bob,host_user_b@host_b,log1");
/* multiline with CTCP */
RECV(":server BATCH +ref draft/multiline #test");
@@ -1666,7 +1668,8 @@ TEST(IrcProtocolWithServer, batch_with_batch_cap)
irc_server_buffer_set_input_multiline (ptr_server, 1);
/* multiline */
RECV(":server BATCH +ref draft/multiline #test");
RECV("@time=2023-08-09T07:43:01.830Z;msgid=icqfzy7zdbpix4gy8pvzuv49kw "
":server BATCH +ref draft/multiline #test");
CHECK_NO_MSG;
RECV("@batch=ref :bob!user_b@host_b PRIVMSG #test :line 1");
CHECK_NO_MSG;
@@ -1675,9 +1678,10 @@ TEST(IrcProtocolWithServer, batch_with_batch_cap)
RECV(":server BATCH -ref");
CHECK_CHAN("bob", "line 1\n"
"line 2",
"irc_privmsg,irc_tag_batch=ref,irc_batch_type_draft/multiline,"
"notify_message,prefix_nick_248,nick_bob,host_user_b@host_b,"
"log1");
"irc_privmsg,irc_tag_batch=ref,irc_tag_time=2023-08-09T07:43:01.830Z,"
"irc_tag_msgid=icqfzy7zdbpix4gy8pvzuv49kw,"
"irc_batch_type_draft/multiline,notify_message,prefix_nick_248,"
"nick_bob,host_user_b@host_b,log1");
/* multiline with CTCP */
RECV(":server BATCH +ref draft/multiline #test");
+91
View File
@@ -21,6 +21,8 @@
#include "CppUTest/TestHarness.h"
#include "tests/tests.h"
extern "C"
{
#include <stdio.h>
@@ -28,6 +30,8 @@ extern "C"
#include "src/core/wee-hook.h"
#include "src/plugins/irc/irc-tag.h"
#include "src/plugins/plugin.h"
extern char *irc_tag_hashtable_to_string (struct t_hashtable *tags);
}
#define WEE_CHECK_ESCAPE_VALUE(__result, __string) \
@@ -161,3 +165,90 @@ TEST(IrcTag, Parse)
hashtable_free (hashtable);
}
/*
* Tests functions:
* irc_tag_add_to_string_cb
* irc_tag_hashtable_to_string
*/
TEST(IrcTag, HashtableToString)
{
char *str;
struct t_hashtable *tags;
POINTERS_EQUAL(NULL, irc_tag_hashtable_to_string (NULL));
tags = hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL, NULL);
CHECK(tags);
WEE_TEST_STR("", irc_tag_hashtable_to_string (tags));
hashtable_set (tags, "time", "2023-08-09T07:43:01.830Z");
hashtable_set (tags, "msgid", "icqfzy7zdbpix4gy8pvzuv49kw");
hashtable_set (tags, "test", "value with spaces");
WEE_TEST_STR("time=2023-08-09T07:43:01.830Z;"
"msgid=icqfzy7zdbpix4gy8pvzuv49kw;"
"test=value\\swith\\sspaces",
irc_tag_hashtable_to_string (tags));
hashtable_free (tags);
}
/*
* Tests functions:
* irc_tag_add_to_hashtable_cb
* irc_tag_add_tags_to_message
*/
TEST(IrcTag, AddTagsToMessage)
{
char *str;
struct t_hashtable *tags;
POINTERS_EQUAL(NULL, irc_tag_add_tags_to_message (NULL, NULL));
WEE_TEST_STR("", irc_tag_add_tags_to_message ("", NULL));
WEE_TEST_STR(":nick!user@host PRIVMSG #test :hello",
irc_tag_add_tags_to_message (
":nick!user@host PRIVMSG #test :hello", NULL));
WEE_TEST_STR("@tag1;tag2=value2 :nick!user@host PRIVMSG #test :hello",
irc_tag_add_tags_to_message (
"@tag1;tag2=value2 :nick!user@host PRIVMSG #test :hello",
NULL));
tags = hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL, NULL);
CHECK(tags);
WEE_TEST_STR(":nick!user@host PRIVMSG #test :hello",
irc_tag_add_tags_to_message (
":nick!user@host PRIVMSG #test :hello", tags));
WEE_TEST_STR("@tag1;tag2=value2 :nick!user@host PRIVMSG #test :hello",
irc_tag_add_tags_to_message (
"@tag1;tag2=value2 :nick!user@host PRIVMSG #test :hello",
tags));
hashtable_set (tags, "time", "2023-08-09T07:43:01.830Z");
hashtable_set (tags, "msgid", "icqfzy7zdbpix4gy8pvzuv49kw");
hashtable_set (tags, "test", "value with spaces");
WEE_TEST_STR("@time=2023-08-09T07:43:01.830Z;msgid=icqfzy7zdbpix4gy8pvzuv49kw;"
"test=value\\swith\\sspaces :nick!user@host PRIVMSG #test :hello",
irc_tag_add_tags_to_message (
":nick!user@host PRIVMSG #test :hello", tags));
WEE_TEST_STR("@tag1;tag2=value2;time=2023-08-09T07:43:01.830Z;"
"msgid=icqfzy7zdbpix4gy8pvzuv49kw;test=value\\swith\\sspaces "
":nick!user@host PRIVMSG #test :hello",
irc_tag_add_tags_to_message (
"@tag1;tag2=value2 :nick!user@host PRIVMSG #test :hello",
tags));
hashtable_free (tags);
}