From 23eef9e1bcbb7a9ada18d55a9198aa13903e571a Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 1 May 2019 12:11:19 +0200 Subject: [PATCH] Simplify linkifyMessage Parsing html as xml has inherent problems, most notable there are many matrix clients that don't escape ampersands in urls of mx-replies, etc. (See issue #18) This also removes the replacement of as it isn't strictly needed. Also the QRegExp is replaced with the Qt5 QRegularExpression for perfomance and because it supports lookahead and lookbehind. I'm pretty sure that the original code also replaced href="" with href=\"\", which was probably wrong, but I'm not to sure about that. Fixes #18 --- src/Config.h | 9 +++++--- src/Utils.cpp | 60 ++------------------------------------------------- 2 files changed, 8 insertions(+), 61 deletions(-) diff --git a/src/Config.h b/src/Config.h index bb99ca8..6aebb51 100644 --- a/src/Config.h +++ b/src/Config.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include // Non-theme app configuration. Layouts, fonts spacing etc. @@ -51,8 +51,11 @@ constexpr auto LABEL_BIG_SIZE_RATIO = 2; namespace strings { const QString url_html = "\\1"; -const QRegExp url_regex( - "((www\\.(?!\\.)|[a-z][a-z0-9+.-]*://)[^\\s<>'\"]+[^!,\\.\\s<>'\"\\]\\)\\:])"); +const QRegularExpression url_regex( + // match an URL, that is not quoted, i.e. + // vvvvvv match quote via negative lookahead/lookbehind vvvvv + // vvvv atomic match url -> fail if there is a " before or after vv + R"regex((?((www\.(?!\.)|[a-z][a-z0-9+.-]*://)[^\s<>'"]+[^!,\.\s<>'"\]\)\:]))(?!"))regex"); } // Window geometry. diff --git a/src/Utils.cpp b/src/Utils.cpp index 0d3e938..f8fdfaf 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -291,65 +291,9 @@ utils::linkifyMessage(const QString &body) { // Convert to valid XML. auto doc = QString("%1").arg(body); + doc.replace(conf::strings::url_regex, conf::strings::url_html); - doc.replace("", ""); - doc.replace("", ""); - doc.replace("
", "

"); - - QXmlStreamReader xml{doc}; - - QString textString; - while (!xml.atEnd() && !xml.hasError()) { - auto t = xml.readNext(); - - switch (t) { - case QXmlStreamReader::Characters: { - auto text = xml.text().toString(); - text.replace(conf::strings::url_regex, conf::strings::url_html); - - textString += text; - break; - } - case QXmlStreamReader::StartDocument: - case QXmlStreamReader::EndDocument: - break; - case QXmlStreamReader::StartElement: { - if (xml.name() == "html") - break; - - textString += QString("<%1").arg(xml.name().toString()); - - const auto attrs = xml.attributes(); - for (const auto &e : attrs) - textString += QString(" %1=\"%2\"") - .arg(e.name().toString()) - .arg(e.value().toString()); - - textString += ">"; - - break; - } - case QXmlStreamReader::EndElement: { - if (xml.name() == "html") - break; - - textString += QString("").arg(xml.name().toString()); - break; - } - default: { - break; - } - } - } - - if (xml.hasError()) { - qWarning() << "error while parsing xml" << xml.errorString() << doc; - doc.replace("", ""); - doc.replace("", ""); - return doc; - } - - return textString; + return doc; } QString