diff --git a/src/core/autotests/utilstest.cpp b/src/core/autotests/utilstest.cpp index e328a81c..347e8651 100644 --- a/src/core/autotests/utilstest.cpp +++ b/src/core/autotests/utilstest.cpp @@ -1,215 +1,217 @@ /* Copyright (c) 2017-2020 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "utilstest.h" #include "utils.h" #include #include #include #include QTEST_GUILESS_MAIN(UtilsTest) UtilsTest::UtilsTest(QObject *parent) : QObject(parent) { } void UtilsTest::shouldGenerateServerUrl_data() { QTest::addColumn("input"); QTest::addColumn("output"); QTest::newRow("empty") << QString() << QUrl(); QTest::newRow("http") << QStringLiteral("http://foo.kde.org/") << QUrl(QStringLiteral("ws://foo.kde.org//websocket")); QTest::newRow("http2") << QStringLiteral("http://foo.kde.org") << QUrl(QStringLiteral("ws://foo.kde.org/websocket")); QTest::newRow("https") << QStringLiteral("https://foo.kde.org") << QUrl(QStringLiteral("wss://foo.kde.org/websocket")); QTest::newRow("withoutscheme") << QStringLiteral("foo.kde.org") << QUrl(QStringLiteral("wss://foo.kde.org/websocket")); } void UtilsTest::shouldGenerateServerUrl() { QFETCH(QString, input); QFETCH(QUrl, output); QCOMPARE(Utils::generateServerUrl(input), output); } void UtilsTest::shouldMarkdownToRichText_data() { QTest::addColumn("input"); QTest::addColumn("output"); QTest::newRow("empty") << QString() << QString(); QTest::newRow("testurl") << QStringLiteral("http://www.kde.org http://www.kde.org") << QStringLiteral("http://www.kde.org http://www.kde.org"); QTest::newRow("bold") << QStringLiteral("*bla*") << QStringLiteral("bla"); QTest::newRow("multi star") << QStringLiteral("**bla**") << QStringLiteral("bla"); QTest::newRow("multi star2") << QStringLiteral("***bla***") << QStringLiteral("***bla***"); QTest::newRow("multi star3") << QStringLiteral("***bla ******") << QStringLiteral("***bla ******"); QTest::newRow("Remove
") << QStringLiteral("foo
") << QStringLiteral("foo"); QTest::newRow("0.6.3") << QStringLiteral("0.6.3") << QStringLiteral("0.6.3"); //Bug 391520 QTest::newRow("multi-line") << QStringLiteral("These are the options:\n- a\n- b") << QStringLiteral("These are the options:
\n- a
\n- b"); } void UtilsTest::shouldMarkdownToRichText() { QFETCH(QString, input); QFETCH(QString, output); QEXPECT_FAIL("bold", "Bug in kf5", Continue); QEXPECT_FAIL("multi star", "Bug in kf5", Continue); QEXPECT_FAIL("Remove
", "Bug in kf5", Continue); QCOMPARE(Utils::markdownToRichText(input), output); } void UtilsTest::shouldExtractRoomUserFromUrl_data() { QTest::addColumn("input"); QTest::addColumn("output"); QTest::newRow("empty") << QString() << QString(); QTest::newRow("extractuser") << QStringLiteral("ruqola:/user/foo") << QStringLiteral("foo"); QTest::newRow("extractroom") << QStringLiteral("ruqola:/room/foo") << QStringLiteral("foo"); QTest::newRow("extractuser") << QStringLiteral("ruqola:/user2/foo") << QStringLiteral("ruqola:/user2/foo"); } void UtilsTest::shouldExtractRoomUserFromUrl() { QFETCH(QString, input); QFETCH(QString, output); QCOMPARE(Utils::extractRoomUserFromUrl(input), output); } void UtilsTest::shouldExtractGenerateRichText_data() { QTest::addColumn("input"); QTest::addColumn("output"); QTest::newRow("empty") << QString() << QString(); QTest::newRow("word@") << QStringLiteral("@foo") << QStringLiteral("@foo"); QTest::newRow("word@-2") << QStringLiteral("@foo.bla") << QStringLiteral("@foo.bla"); QTest::newRow("word@-3") << QStringLiteral("@foo.bla.bli") << QStringLiteral("@foo.bla.bli"); QTest::newRow("word@-4") << QStringLiteral("@foo.bla.bli dd") << QStringLiteral("@foo.bla.bli dd"); QTest::newRow("word@-5") << QStringLiteral("bla bla 21 @foo.bla.bli dd") << QStringLiteral("bla bla 21 @foo.bla.bli dd"); QTest::newRow("word@-6") << QStringLiteral("@foo-bla") << QStringLiteral("@foo-bla"); QTest::newRow("word@-7") << QStringLiteral("@foo_bla") << QStringLiteral("@foo_bla"); QTest::newRow("word@-8") << QStringLiteral("bli@foo_bla") << QStringLiteral("bli@foo_bla"); QTest::newRow("word#") << QStringLiteral("#foo") << QStringLiteral("#foo"); QTest::newRow("word#-2") << QStringLiteral("#foo.bla") << QStringLiteral("#foo.bla"); QTest::newRow("word#-3") << QStringLiteral("#foo.bla.bli") << QStringLiteral("#foo.bla.bli"); QTest::newRow("word#-4") << QStringLiteral("#foo.bla.bli dd") << QStringLiteral("#foo.bla.bli dd"); QTest::newRow("word#-5") << QStringLiteral("bla bla 21 #foo.bla.bli dd") << QStringLiteral("bla bla 21 #foo.bla.bli dd"); QTest::newRow("word#-6") << QStringLiteral("#foo-bla") << QStringLiteral("#foo-bla"); QTest::newRow("word#-7") << QStringLiteral("#foo_bla") << QStringLiteral("#foo_bla"); //Test parsing when it's in an url... don't replace it. QTest::newRow("url") << QStringLiteral("http://www.kde.org#foo_bla") << QStringLiteral("http://www.kde.org#foo_bla"); QTest::newRow("0.6.3") << QStringLiteral("0.6.3") << QStringLiteral("0.6.3"); } void UtilsTest::shouldExtractGenerateRichText() { QFETCH(QString, input); QFETCH(QString, output); QCOMPARE(Utils::generateRichText(input, QString()), output); } void UtilsTest::shouldHighlightText_data() { QTest::addColumn("input"); QTest::addColumn("username"); QTest::addColumn("output"); QTest::newRow("empty") << QString() << QString() << QString(); QTest::newRow("word@1") << QStringLiteral("@foo") << QString() << QStringLiteral("@foo"); QTest::newRow("word@1-username") << QStringLiteral("@foo") << QStringLiteral("foo") << QStringLiteral("@foo"); QTest::newRow("word@2-username") << QStringLiteral("bla bla @foo") << QStringLiteral("foo") << QStringLiteral("bla bla @foo"); } void UtilsTest::shouldHighlightText() { QFETCH(QString, input); QFETCH(QString, username); QFETCH(QString, output); QCOMPARE(Utils::generateRichText(input, username), output); } void UtilsTest::shouldParseNotification_data() { QTest::addColumn("fileName"); QTest::addColumn("title"); QTest::addColumn("message"); QTest::addColumn("sender"); QTest::newRow("notification1") << QStringLiteral("notification") << QStringLiteral("title") << QStringLiteral("pong") << QStringLiteral("tgrk5CZKgYGiSSqXp"); //TODO QTest::newRow("notificationencrypted") << QStringLiteral("notificationencrypted") << QStringLiteral("title") << QStringLiteral("pong") << QStringLiteral("tgrk5CZKgYGiSSqXp"); } void UtilsTest::shouldParseNotification() { QFETCH(QString, fileName); QFETCH(QString, title); QFETCH(QString, message); QFETCH(QString, sender); const QString originalJsonFile = QLatin1String(RUQOLA_DATA_DIR) + QLatin1String("/json/") + fileName + QLatin1String(".json"); QFile f(originalJsonFile); QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray content = f.readAll(); f.close(); const QJsonDocument doc = QJsonDocument::fromJson(content); const QJsonObject fields = doc.object().value(QLatin1String("fields")).toObject(); const QJsonArray contents = fields.value(QLatin1String("args")).toArray(); QString parseTitle; QString parseMessage; QString parseSender; Utils::parseNotification(contents, parseMessage, parseTitle, parseSender); QEXPECT_FAIL("notificationencrypted", "Encrypted message not supported yet", Continue); QCOMPARE(parseMessage, message); QCOMPARE(parseTitle, title); QEXPECT_FAIL("notificationencrypted", "Encrypted message not supported yet", Continue); QCOMPARE(parseSender, sender); } void UtilsTest::shouldConvertTextWithUrl_data() { QTest::addColumn("text"); QTest::addColumn("convertedText"); QTest::newRow("empty") << QString() << QString(); QTest::newRow("onlytext") << QStringLiteral("foo bla bli") << QStringLiteral("foo bla bli"); QTest::newRow("test1") << QStringLiteral("[blo](http://www.kde.org)") << QStringLiteral("blo"); QTest::newRow("test2") << QStringLiteral("[](http://www.kde.org)") << QStringLiteral("(http://www.kde.org)"); QTest::newRow("test3") << QStringLiteral("bla bla [blo](http://www.kde.org)") << QStringLiteral("bla bla blo"); QTest::newRow("test4") << QStringLiteral("bla bla [blo](http://www.kde.org) bli [blu](http://www.kdi.org)") << QStringLiteral("bla bla blo bli blu"); + QTest::newRow("test4") << QStringLiteral("bla bla [blo]") << QStringLiteral("bla bla [blo]"); + QTest::newRow("test4") << QStringLiteral("bla bla [blo] bli") << QStringLiteral("bla bla [blo] bli"); } void UtilsTest::shouldConvertTextWithUrl() { QFETCH(QString, text); QFETCH(QString, convertedText); QCOMPARE(Utils::convertTextWithUrl(text), convertedText); } diff --git a/src/core/utils.cpp b/src/core/utils.cpp index 379d15d5..e66c10ad 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -1,217 +1,220 @@ /* Copyright (c) 2017-2020 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "utils.h" #include "ruqola_debug.h" #include #include #include #include #include QUrl Utils::generateServerUrl(const QString &url) { if (url.isEmpty()) { return {}; } QString serverUrl = url; if (serverUrl.startsWith(QLatin1String("https://"))) { serverUrl.replace(QLatin1String("https://"), QLatin1String("wss://")); } else if (serverUrl.startsWith(QLatin1String("http://"))) { serverUrl.replace(QLatin1String("http://"), QLatin1String("ws://")); } else { serverUrl = QLatin1String("wss://") + serverUrl; } return QUrl(serverUrl + QStringLiteral("/websocket")); } QString Utils::extractRoomUserFromUrl(QString url) { url.remove(QStringLiteral("ruqola:/user/")); url.remove(QStringLiteral("ruqola:/room/")); return url; } QString Utils::markdownToRichText(const QString &markDown) { //qCDebug(RUQOLA_LOG) << "BEFORE markdownToRichText "< need to investigate //str.remove(QStringLiteral("
")); //qCDebug(RUQOLA_LOG) << "markdownToRichText "<@%1").arg(word)); } else { newStr.replace(QLatin1Char('@') + word, QStringLiteral("@%1").arg(word)); } } static const QRegularExpression regularExpressionRoom(QStringLiteral("(^|\\s+)#([\\w._-]+)")); QRegularExpressionMatchIterator roomIterator = regularExpressionRoom.globalMatch(newStr); while (roomIterator.hasNext()) { const QRegularExpressionMatch match = roomIterator.next(); const QStringRef word = match.capturedRef(2); newStr.replace(QLatin1Char('#') + word, QStringLiteral("#%1").arg(word)); } return newStr; } QString Utils::presenceStatusToString(User::PresenceStatus status) { switch (status) { case User::PresenceStatus::PresenceOnline: return QStringLiteral("online"); case User::PresenceStatus::PresenceBusy: return QStringLiteral("busy"); case User::PresenceStatus::PresenceAway: return QStringLiteral("away"); case User::PresenceStatus::PresenceOffline: return QStringLiteral("offline"); case User::PresenceStatus::Unknown: return {}; } return {}; } QString Utils::iconFromStatus(const QString &status) { if (status == QLatin1String("online")) { return QStringLiteral("user-online"); } else if (status == QLatin1String("busy")) { return QStringLiteral("user-busy"); } else if (status == QLatin1String("away")) { return QStringLiteral("user-away"); } else if (status == QLatin1String("offline")) { return QStringLiteral("user-offline"); } else { qCDebug(RUQOLA_LOG) << "Problem with status " << status; return QStringLiteral("unknown"); } qCDebug(RUQOLA_LOG) << " QString User::iconFromStatus() const" << status; return {}; } User::PresenceStatus Utils::presenceStatusFromString(const QString &status) { if (status == QLatin1String("online")) { return User::PresenceStatus::PresenceOnline; } else if (status == QLatin1String("busy")) { return User::PresenceStatus::PresenceBusy; } else if (status == QLatin1String("away")) { return User::PresenceStatus::PresenceAway; } else if (status == QLatin1String("offline")) { return User::PresenceStatus::PresenceOffline; } else { qCDebug(RUQOLA_LOG) << "Problem with status " << status; return User::PresenceStatus::Unknown; } } void Utils::parseNotification(const QJsonArray &contents, QString &message, QString &title, QString &sender) { QJsonObject obj = contents.at(0).toObject(); message = obj[QStringLiteral("text")].toString(); title = obj[QStringLiteral("title")].toString(); obj = obj.value(QLatin1String("payload")).toObject(); if (!obj.isEmpty()) { obj = obj.value(QLatin1String("sender")).toObject(); if (!obj.isEmpty()) { sender = obj.value(QLatin1String("_id")).toString(); } else { qCDebug(RUQOLA_LOG) << "Problem with notification json: missing sender"; } } else { qCDebug(RUQOLA_LOG) << "Problem with notification json: missing payload"; } } QString Utils::userIdFromDirectChannel(const QString &rid, const QString &userId) { QString newUserId = rid; newUserId.remove(userId); return newUserId; } qint64 Utils::parseDate(const QString &key, const QJsonObject &o) { return o.value(key).toObject().value(QLatin1String("$date")).toDouble(-1); } qint64 Utils::parseIsoDate(const QString &key, const QJsonObject &o) { if (o.contains(key)) { return QDateTime::fromString(o.value(key).toString(), Qt::ISODate).toMSecsSinceEpoch(); } else { return -1; } } QString Utils::convertTextWithUrl(const QString &str) { QString newStr; bool isRef = false; bool isUrl = false; QString url; QString references; for (int i = 0; i < str.count(); ++i) { if (str.at(i) == QLatin1Char('[')) { isRef = true; } else if (str.at(i) == QLatin1Char(']')) { isRef = false; + if ((i == str.count() - 1) || (str.at(i+1) != QLatin1Char('('))) { + newStr += QLatin1Char('[') + references + QLatin1Char(']'); + } } else if (str.at(i) == QLatin1Char('(') && !references.isEmpty()) { isUrl = true; } else if (str.at(i) == QLatin1Char(')') && !references.isEmpty()) { isUrl = false; newStr += QStringLiteral("%2").arg(url, references); references.clear(); url.clear(); } else { if (isRef) { references += str.at(i); } else if (isUrl) { url += str.at(i); } else { newStr += str.at(i); } } } return newStr; }