diff --git a/src/aotextarea.cpp b/src/aotextarea.cpp
index 08885da80..32f61dbb2 100644
--- a/src/aotextarea.cpp
+++ b/src/aotextarea.cpp
@@ -27,7 +27,20 @@ void AOTextArea::addMessage(QString name, QString message, QString nameColor, QS
message += " ";
}
- QString result = message.toHtmlEscaped().replace("\n", "
").replace(url_parser_regex, "\\1");
+ // Detect URLs before HTML escaping to prevent & from becoming & in links
+ QString result;
+ int lastEnd = 0;
+ QRegularExpressionMatchIterator it = url_parser_regex.globalMatch(message);
+ while (it.hasNext())
+ {
+ QRegularExpressionMatch match = it.next();
+ result += message.mid(lastEnd, match.capturedStart() - lastEnd).toHtmlEscaped();
+ QString url = match.captured(1);
+ result += "" + url.toHtmlEscaped() + "";
+ lastEnd = match.capturedEnd();
+ }
+ result += message.mid(lastEnd).toHtmlEscaped();
+ result.replace("\n", "
");
if (!messageColor.isEmpty())
{
diff --git a/src/lobby.cpp b/src/lobby.cpp
index c62f3e06f..c684c4071 100644
--- a/src/lobby.cpp
+++ b/src/lobby.cpp
@@ -595,7 +595,20 @@ void Lobby::set_server_description(const QString &server_description)
{
ui_server_description_text->clear();
static QRegularExpression regexp_links("\\b(https?://\\S+\\.\\S+)\\b");
- QString result = server_description.toHtmlEscaped().replace("\n", "
").replace(regexp_links, "\\1");
+ // Detect URLs before HTML escaping to prevent & from becoming & in links
+ QString result;
+ int lastEnd = 0;
+ QRegularExpressionMatchIterator it = regexp_links.globalMatch(server_description);
+ while (it.hasNext())
+ {
+ QRegularExpressionMatch match = it.next();
+ result += server_description.mid(lastEnd, match.capturedStart() - lastEnd).toHtmlEscaped();
+ QString url = match.captured(1);
+ result += "" + url.toHtmlEscaped() + "";
+ lastEnd = match.capturedEnd();
+ }
+ result += server_description.mid(lastEnd).toHtmlEscaped();
+ result.replace("\n", "
");
ui_server_description_text->insertHtml(result);
}