aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-11-08 22:05:03 +0100
committerdec05eba <dec05eba@protonmail.com>2022-11-08 22:05:03 +0100
commitdeb32bded40c4c46ce57c729c303edcb1915458b (patch)
tree66bac3d9ccf67e30fa21f7682ab8f21f98c1af1c
parentd8cccb74066545c534bb9952f51e441d4aba2c66 (diff)
html parser: fix possible endless loop. Fixes matrix chat where parsing non-html as html happened
m---------depends/html-parser0
m---------depends/html-search0
-rw-r--r--plugins/Matrix.hpp2
-rw-r--r--src/QuickMedia.cpp12
-rw-r--r--src/plugins/Matrix.cpp71
5 files changed, 60 insertions, 25 deletions
diff --git a/depends/html-parser b/depends/html-parser
-Subproject 684a3bc56d5c40ed3eb54ca263751fa4724e73f
+Subproject 66ec83b862ea2a8dbda1c1f3663af88a8d12d9b
diff --git a/depends/html-search b/depends/html-search
-Subproject 3dbbcc75199bd996163500beb39a6e902bc7ddc
+Subproject 0dd5817eecb3a8db9338394e2c164119a92d4db
diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp
index 4afe28e..ac3ca3b 100644
--- a/plugins/Matrix.hpp
+++ b/plugins/Matrix.hpp
@@ -20,7 +20,6 @@ namespace QuickMedia {
static const int AUTHOR_MAX_LENGTH = 48;
- std::string remove_reply_formatting(const std::string &str);
std::string extract_first_line_remove_newline_elipses(const std::string &str, size_t max_length);
mgl::Color user_id_to_color(const std::string &user_id);
std::string formatted_text_to_qm_text(const char *str, size_t size, bool allow_formatted_text);
@@ -103,6 +102,7 @@ namespace QuickMedia {
RelatedEventType related_event_type = RelatedEventType::NONE;
bool notification_mentions_me = false;
bool cache = false;
+ bool body_is_formatted = false;
std::string transaction_id;
time_t timestamp = 0; // In milliseconds
MessageType type;
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 72df6eb..c9c7603 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -5319,10 +5319,17 @@ namespace QuickMedia {
return load_cached_related_embedded_item(body_item, message, me.get(), current_room->get_user_display_name(me), me->user_id, message_body_items);
}
+ static std::string message_to_qm_text(Message *message) {
+ if(message->body_is_formatted)
+ return formatted_text_to_qm_text(message->body.c_str(), message->body.size(), true);
+ else
+ return message->body;
+ }
+
static std::shared_ptr<BodyItem> message_to_body_item(RoomData *room, Message *message, const std::string &my_display_name, const std::string &my_user_id) {
auto body_item = BodyItem::create("");
body_item->set_author(extract_first_line_remove_newline_elipses(room->get_user_display_name(message->user), AUTHOR_MAX_LENGTH));
- body_item->set_description(strip(formatted_text_to_qm_text(message->body.c_str(), message->body.size(), true)));
+ body_item->set_description(strip(message_to_qm_text(message)));
body_item->set_timestamp(message->timestamp);
if(!message->thumbnail_url.empty()) {
body_item->thumbnail_url = message->thumbnail_url;
@@ -5652,7 +5659,7 @@ namespace QuickMedia {
// TODO: Properly check reply message objects for mention of user instead of message data, but only when synapse fixes that notifications
// are not triggered by reply to a message with our display name/user id.
Message *edited_message_ref = static_cast<Message*>(body_item->userdata);
- std::string qm_formatted_text = formatted_text_to_qm_text(message->body.c_str(), message->body.size(), true);
+ std::string qm_formatted_text = message_to_qm_text(message.get());
body_item->set_description(std::move(qm_formatted_text));
if(message->user != me && message_contains_user_mention(message.get(), my_display_name, me->user_id))
@@ -6116,6 +6123,7 @@ namespace QuickMedia {
}
auto message = std::make_shared<Message>();
+ message->body_is_formatted = true;
message->user = matrix->get_me(current_room);
if(msgtype == "m.emote")
message->body = "*" + current_room->get_user_display_name(me) + "* " + matrix->body_to_formatted_body(current_room, text);
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index d1a060d..31aab76 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -117,6 +117,34 @@ namespace QuickMedia {
return colors[color_hash_code(user_id) % num_colors];
}
+ static std::string remove_reply_formatting(const std::string &str) {
+ if(strncmp(str.c_str(), "> <@", 4) == 0) {
+ size_t index = str.find("> ", 4);
+ if(index != std::string::npos) {
+ size_t msg_begin = str.find("\n\n", index + 2);
+ if(msg_begin != std::string::npos)
+ return str.substr(msg_begin + 2);
+ }
+ } else {
+ return formatted_text_to_qm_text(str.c_str(), str.size(), false);
+ }
+ return str;
+ }
+
+ static std::string remove_reply_formatting(const Message *message) {
+ if(!message->body_is_formatted && strncmp(message->body.c_str(), "> <@", 4) == 0) {
+ size_t index = message->body.find("> ", 4);
+ if(index != std::string::npos) {
+ size_t msg_begin = message->body.find("\n\n", index + 2);
+ if(msg_begin != std::string::npos)
+ return message->body.substr(msg_begin + 2);
+ }
+ return message->body;
+ } else {
+ return formatted_text_to_qm_text(message->body.c_str(), message->body.size(), false);
+ }
+ }
+
bool TimestampedDisplayData::set_data_if_newer(std::string new_data, time_t new_timestamp) {
if(new_timestamp == 0) {
data = std::move(new_data);
@@ -433,7 +461,7 @@ namespace QuickMedia {
if(!sync_is_cache && message_dir == MessageDirection::AFTER) {
for(auto &message : messages) {
if(message->notification_mentions_me) {
- std::string body = remove_reply_formatting(message->body);
+ std::string body = remove_reply_formatting(message.get());
bool read = true;
// TODO: What if the message or username begins with "-"? also make the notification image be the avatar of the user
if((!is_window_focused || room != current_room) && message->related_event_type != RelatedEventType::EDIT && message->related_event_type != RelatedEventType::REDACTION) {
@@ -598,8 +626,15 @@ namespace QuickMedia {
return nullptr;
}
+ static std::string message_to_qm_text(const Message *message, bool allow_formatted_text = true) {
+ if(message->body_is_formatted)
+ return formatted_text_to_qm_text(message->body.c_str(), message->body.size(), allow_formatted_text);
+ else
+ return message->body;
+ }
+
static std::string message_to_room_description_text(Message *message) {
- std::string body = strip(formatted_text_to_qm_text(message->body.c_str(), message->body.size(), true));
+ std::string body = strip(message_to_qm_text(message));
if(message->type == MessageType::REACTION)
return "Reacted with: " + body;
else if(message->related_event_type == RelatedEventType::REPLY)
@@ -2130,7 +2165,7 @@ namespace QuickMedia {
}
bool message_contains_user_mention(const Message *message, const std::string &username, const std::string &user_id) {
- const std::string formatted_text = formatted_text_to_qm_text(message->body.c_str(), message->body.size(), false);
+ const std::string formatted_text = message_to_qm_text(message, false);
return message_contains_user_mention(formatted_text, username) || message_contains_user_mention(formatted_text, user_id);
}
@@ -2197,7 +2232,7 @@ namespace QuickMedia {
// TODO: Is @room ok? shouldn't we also check if the user has permission to do @room? (only when notifications are limited to @mentions)
// TODO: Is comparing against read marker timestamp ok enough?
if(me && message->timestamp > read_marker_message_timestamp) {
- std::string message_str = formatted_text_to_qm_text(message->body.c_str(), message->body.size(), false);
+ std::string message_str = message_to_qm_text(message.get(), false);
message->notification_mentions_me = message_contains_user_mention(message_str, my_display_name) || message_contains_user_mention(message_str, me->user_id) || message_contains_user_mention(message_str, "@room");
}
}
@@ -2370,8 +2405,10 @@ namespace QuickMedia {
code_parse_userdata.allow_formatted_text = true;
code_parse_userdata.inside_source_highlight = true;
html_parser_parse(output.c_str(), output.size(), formattext_text_parser_callback, &code_parse_userdata);
- text_to_add = std::move(code_parse_userdata.result);
- formatted_text_flags = FORMATTED_TEXT_FLAG_NONE;
+ if(!code_parse_userdata.result.empty()) {
+ text_to_add = std::move(code_parse_userdata.result);
+ formatted_text_flags = FORMATTED_TEXT_FLAG_NONE;
+ }
}
}
}
@@ -2775,9 +2812,12 @@ namespace QuickMedia {
if(!body_json.IsString())
return nullptr;
+ bool body_is_formatted = true;
const rapidjson::Value *formatted_body_json = &GetMember(*content_json, "formatted_body");
- if(!formatted_body_json->IsString())
+ if(!formatted_body_json->IsString()) {
formatted_body_json = &body_json;
+ body_is_formatted = false;
+ }
auto message = std::make_shared<Message>();
std::string prefix;
@@ -2846,6 +2886,7 @@ namespace QuickMedia {
message->user = user;
message->event_id = event_id_str;
message->body = prefix + std::string(formatted_body_json->GetString(), formatted_body_json->GetStringLength());
+ message->body_is_formatted = body_is_formatted;
message->related_event_id = std::move(related_event_id);
message->related_event_type = related_event_type;
message->timestamp = timestamp;
@@ -3567,20 +3608,6 @@ namespace QuickMedia {
return PluginResult::OK;
}
- std::string remove_reply_formatting(const std::string &str) {
- if(strncmp(str.c_str(), "> <@", 4) == 0) {
- size_t index = str.find("> ", 4);
- if(index != std::string::npos) {
- size_t msg_begin = str.find("\n\n", index + 2);
- if(msg_begin != std::string::npos)
- return str.substr(msg_begin + 2);
- }
- } else {
- return formatted_text_to_qm_text(str.c_str(), str.size(), false);
- }
- return str;
- }
-
static std::string block_quote(const std::string &str) {
std::string result;
for(char c : str) {
@@ -3600,7 +3627,7 @@ namespace QuickMedia {
switch(message->type) {
case MessageType::TEXT: {
if(message->related_event_type != RelatedEventType::NONE)
- related_to_body = remove_reply_formatting(message->body);
+ related_to_body = remove_reply_formatting(message);
else
related_to_body = message->body;
break;