From cad5ed7635d6e68c8ec91e5bdebb9a708b97d0fe Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 8 Dec 2022 17:40:49 +0100 Subject: [PATCH] Implement RFC3987 for parsing IRI (NonASCII characters in URL) to allow chat redirections on URL. Move QML code into C++ in order to have an updated API that take account of unicode formats. Fix images display that comes from URL in chats. (cherry picked from commit 8df33fc5468dba56f3ce09de87c3828578f50af2) --- CHANGELOG.md | 5 + linphone-app/CMakeLists.txt | 2 + linphone-app/resources.qrc | 1 - linphone-app/src/utils/UriTools.cpp | 293 ++++++++++++++++++ linphone-app/src/utils/UriTools.hpp | 57 ++++ linphone-app/src/utils/Utils.cpp | 43 +++ linphone-app/src/utils/Utils.hpp | 1 + .../modules/Linphone/Chat/ChatTextMessage.qml | 2 +- .../Linphone/Styles/Chat/ChatStyle.qml | 3 +- linphone-app/ui/scripts/Utils/uri-tools.js | 164 ---------- linphone-app/ui/scripts/Utils/utils.js | 80 ----- 11 files changed, 404 insertions(+), 247 deletions(-) create mode 100644 linphone-app/src/utils/UriTools.cpp create mode 100644 linphone-app/src/utils/UriTools.hpp delete mode 100644 linphone-app/ui/scripts/Utils/uri-tools.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ccfeacda..33a13464e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 5.0.1 - 2022-12-09 + +### Fixed +- RF3987 to allow IRI parsing in chats. +- Image display in chats from an URL. ## 5.0.0 - 2022-12-07 diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt index 431756981..68475b362 100644 --- a/linphone-app/CMakeLists.txt +++ b/linphone-app/CMakeLists.txt @@ -262,6 +262,7 @@ set(SOURCES src/utils/LinphoneEnums.cpp src/utils/MediastreamerUtils.cpp src/utils/QExifImageHeader.cpp + src/utils/UriTools.cpp src/utils/Utils.cpp src/utils/plugins/PluginsManager.cpp ) @@ -398,6 +399,7 @@ set(HEADERS src/utils/LinphoneEnums.hpp src/utils/MediastreamerUtils.hpp src/utils/QExifImageHeader.hpp + src/utils/UriTools.hpp src/utils/Utils.hpp src/utils/plugins/PluginsManager.hpp ) diff --git a/linphone-app/resources.qrc b/linphone-app/resources.qrc index a5ff5052e..7ebb4a073 100644 --- a/linphone-app/resources.qrc +++ b/linphone-app/resources.qrc @@ -426,7 +426,6 @@ ui/modules/Linphone/View/SipAddressesView.qml ui/scripts/Utils/port-tools.js ui/scripts/Utils/qmldir - ui/scripts/Utils/uri-tools.js ui/scripts/Utils/utils.js ui/views/App/qmldir ui/views/App/Calls/AbstractStartingCall.qml diff --git a/linphone-app/src/utils/UriTools.cpp b/linphone-app/src/utils/UriTools.cpp new file mode 100644 index 000000000..2e8c1121f --- /dev/null +++ b/linphone-app/src/utils/UriTools.cpp @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2010-2023 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +// ============================================================================= +// Library to deal with IRI and URI. +// See: +// IRI : https://tools.ietf.org/html/rfc3987 +// URI : https://tools.ietf.org/html/rfc3986 +// ============================================================================= + +#include "UriTools.hpp" + +static UriTools gUriTools; + +UriTools::UriTools(){ + initRegularExpressions(); +} + +QVector > UriTools::parseIri(const QString& text){ + return parse(text, gUriTools.mIriRegularExpression); +} + +QVector > UriTools::parseUri(const QString& text){ + return parse(text, gUriTools.mUriRegularExpression); +} + +// Parse a text and return all lines where regex is matched or not +QVector > UriTools::parse(const QString& text, const QRegularExpression regex){ + QVector > results; + int currentIndex = 0; + auto match = regex.match(text); + + for (int i = 0; i <= match.lastCapturedIndex(); ++i) { + int startIndex = match.capturedStart(i); + if(currentIndex != startIndex){ + results.push_back({false, text.mid(currentIndex, startIndex - currentIndex)}); + } + results.push_back({true, match.captured(i)}); + currentIndex = startIndex; + } + + if(results.size() == 0) + results.push_back({false, text}); + else{ + currentIndex += results.back().second.length(); + if( currentIndex < text.size()) + results.push_back({false, text.mid(currentIndex)}); + } + return results; +} + +void UriTools::initRegularExpressions() { + // Level 0. -------------------------------------------------------------------- + QString URI_DEC_OCTET = QString("(?:") + + "25[0-5]" + + "|" + "2[0-4]\\d" + + "|" + "1\\d{2}" + + "|" + "[1-9]\\d" + + "|" + "\\d" + + ")"; + + QString URI_H16 = "[0-9A-Fa-f]{1,4}"; + QString URI_PCT_ENCODED = "%[A-Fa-f\\d]{2}"; + QString URI_PORT = "\\d*"; + QString URI_SCHEME = "[a-zA-Z][\\w+\\.\\-]*"; + QString URI_SUB_DELIMS = "[!$&\"()*+,;=]"; + QString URI_UNRESERVED = "[\\w\\._~\\-]"; + QString IRI_UCS_CHAR = QString("(?:") + + "[\\x{00A0}-\\x{D7FF}]" + "|" + "[\\x{F900}-\\x{FDCF}]" + "|" + "[\\x{FDF0}-\\x{FFEF}]" + + "|" + "[\\x{10000}-\\x{1FFFD}]" + "|" + "[\\x{20000}-\\x{2FFFD}]" + "|" + "[\\x{30000}-\\x{3FFFD}]" + + //"|" + "[\\x{D800\\x{DC00}-\\x{D83F\\x{DFFD}]" + "|" + "[\\x{D840\\x{DC00}-\\x{D87F\\x{DFFD}]" + "|" + "[\\x{D880\\x{DC00}-\\x{D8BF\\x{DFFD}]" + + + "|" + "[\\x{40000}-\\x{4FFFD}]" + "|" + "[\\x{50000}-\\x{5FFFD}]" + "|" + "[\\x{60000}-\\x{6FFFD}]" + + //"|" + "[\\x{D8C0\\x{DC00}-\\x{D8FF\\x{DFFD}]" + "|" + "[\\x{D900\\x{DC00}-\\x{D93F\\x{DFFD}]" + "|" + "[\\x{D940\\x{DC00}-\\x{D97F\\x{DFFD}]" + + + "|" + "[\\x{70000}-\\x{7FFFD}]" + "|" + "[\\x{80000}-\\x{8FFFD}]" + "|" + "[\\x{90000}-\\x{9FFFD}]" + + //"|" + "[\\x{D980\\x{DC00}-\\x{D9BF\\x{DFFD}]" + "|" + "[\\x{D9C0\\x{DC00}-\\x{D9FF\\x{DFFD}]" + "|" + "[\\x{DA00\\x{DC00}-\\x{DA3F\\x{DFFD}]" + + + "|" + "[\\x{A0000}-\\x{AFFFD}]" + "|" + "[\\x{B0000}-\\x{BFFFD}]" + "|" + "[\\x{C0000}-\\x{CFFFD}]" + + //"|" + "[\\x{DA40\\x{DC00}-\\x{DA7F\\x{DFFD}]" + "|" + "[\\x{DA80\\x{DC00}-\\x{DABF\\x{DFFD}]" + "|" + "[\\x{DAC0\\x{DC00}-\\x{DAFF\\x{DFFD}]" + + + "|" + "[\\x{D0000}-\\x{DFFFD}]" + "|" + "[\\x{E1000}-\\x{EFFFD}]" + + //"|" + "[\\x{DB00\\x{DC00}-\\x{DB3F\\x{DFFD}]" + "|" + "[\\x{DB44\\x{DC00}-\\x{DB7F\\x{DFFD}]" + + ")"; + + QString IRI_PRIVATE = QString("(?:") + + "[\\x{E000}-\\x{F8FF}]" + + "|" + "[\\x{F0000}-\\x{FFFFD}]" + "|" + "[\\x{100000}-\\x{10FFFD}]" + + //"|" + "[\\x{DBC0\\x{DC00}-\\x{DBFF\\x{DFFD}]" + "|" + "[\\x{DBC0\\x{DC00}-\\x{DBFF\\x{DFFD}]" + + ")"; + + + // Level 1. -------------------------------------------------------------------- + QString URI_IPV_FUTURE = QString("v[0-9A-Fa-f]+\\.") + "(?:" + + URI_UNRESERVED + + URI_SUB_DELIMS + + ":" + + ")"; + + QString IRI_UNRESERVED = QString("(?:") + + "[\\w\\._~\\-]" + + "|" + IRI_UCS_CHAR + + ")"; + + QString URI_IPV4_ADDRESS = URI_DEC_OCTET + "\\." + URI_DEC_OCTET + "\\." + + URI_DEC_OCTET + "\\." + URI_DEC_OCTET; + + QString URI_PCHAR = "(?:" + + URI_UNRESERVED + + "|" + URI_PCT_ENCODED + + "|" + URI_SUB_DELIMS + + "|" + "[:@]" + + ")"; + + QString URI_REG_NAME = "(?:" + + URI_UNRESERVED + + "|" + URI_PCT_ENCODED + + "|" + URI_SUB_DELIMS + + ")*"; + + QString URI_USERINFO = "(?:" + + URI_UNRESERVED + + "|" + URI_PCT_ENCODED + + "|" + URI_SUB_DELIMS + + "|" + ":" + + ")*"; + + // Level 2. -------------------------------------------------------------------- + + QString URI_FRAGMENT = "(?:" + + URI_PCHAR + + "|" + "[/?]" + + ")*"; + + QString URI_LS32 = "(?:" + + URI_H16 + ":" + URI_H16 + + "|" + URI_IPV4_ADDRESS + + ")"; + + QString URI_QUERY = "(?:" + + URI_PCHAR + + "|" + "[/?]" + + ")*"; + + QString URI_SEGMENT = URI_PCHAR + "*"; + + QString URI_SEGMENT_NZ = URI_PCHAR + "+"; + + QString IRI_PCHAR = "(?:" + + IRI_UNRESERVED + + "|" + URI_PCT_ENCODED + + "|" + URI_SUB_DELIMS + + "|" + "[:@]" + + ")"; + + QString IRI_REG_NAME = "(?:" + + IRI_UNRESERVED + + "|" + URI_PCT_ENCODED + + "|" + URI_SUB_DELIMS + + ")*"; + + QString IRI_USERINFO = "(?:" + + IRI_UNRESERVED + + "|" + URI_PCT_ENCODED + + "|" + URI_SUB_DELIMS + + "|" + ":" + + ")*"; + + // Level 3. -------------------------------------------------------------------- + + QString URI_IPV6_ADDRESS = QString("(?:") + + "(?:" + URI_H16 + ":){6}" + URI_LS32 + + "|" + "::(?:" + URI_H16 + ":){5}" + URI_LS32 + + "|" + "\\[" + URI_H16 + "\\]::(?:" + URI_H16 + ":){4}" + URI_LS32 + + "|" + "\\[" + "(?:" + URI_H16 + ":)?" + URI_H16 + "\\]::(?:" + URI_H16 + ":){3}" + URI_LS32 + + "|" + "\\[" + "(?:" + URI_H16 + ":){0,2}" + URI_H16 + "\\]::(?:" + URI_H16 + ":){2}" + URI_LS32 + + "|" + "\\[" + "(?:" + URI_H16 + ":){0,3}" + URI_H16 + "\\]::" + URI_H16 + ":" + URI_LS32 + + "|" + "\\[" + "(?:" + URI_H16 + ":){0,4}" + URI_H16 + "\\]::" + URI_LS32 + + "|" + "\\[" + "(?:" + URI_H16 + ":){0,5}" + URI_H16 + "\\]::" + URI_H16 + + "|" + "\\[" + "(?:" + URI_H16 + ":){0,6}" + URI_H16 + "\\]::" + + ")"; + + QString URI_PATH_ABEMPTY = QString("(?:") + "/" + URI_SEGMENT + ")*"; + + QString URI_PATH_ABSOLUTE = QString("/") + + "(?:" + URI_SEGMENT_NZ + "(?:" + "/" + URI_SEGMENT + ")*" + ")?"; + + QString URI_PATH_ROOTLESS = + URI_SEGMENT_NZ + "(?:" + "/" + URI_SEGMENT + ")*"; + + QString IRI_FRAGMENT = "(?:" + + IRI_PCHAR + + "|" + "[/?]" + + ")*"; + + QString IRI_QUERY = "(?:" + + IRI_PCHAR + + "|" + IRI_PRIVATE + + "|" + "[/?]" + + ")*"; + + QString IRI_SEGMENT = IRI_PCHAR + "*"; + QString IRI_SEGMENT_NZ = IRI_PCHAR + "+"; + + + // Level 4. -------------------------------------------------------------------- + + QString URI_IP_LITERAL = QString("\\[" )+ + "(?:" + + URI_IPV6_ADDRESS + + "|" + URI_IPV_FUTURE + + ")" + + "\\]"; + + QString IRI_PATH_ABEMPTY = QString("(?:") + "/" + IRI_SEGMENT + ")*"; + + QString IRI_PATH_ABSOLUTE = QString("/") + + "(?:" + IRI_SEGMENT_NZ + "(?:" + "/" + IRI_SEGMENT + ")*" + ")?"; + + QString IRI_PATH_ROOTLESS = + IRI_SEGMENT_NZ + "(?:" + "/" + IRI_SEGMENT + ")*"; + + + // Level 5. -------------------------------------------------------------------- + + QString URI_HOST = "(?:" + + URI_REG_NAME + + "|" + URI_IPV4_ADDRESS + + "|" + URI_IP_LITERAL + + ")"; + + QString IRI_HOST = "(?:" + + IRI_REG_NAME + + "|" + URI_IPV4_ADDRESS + + "|" + URI_IP_LITERAL + + ")"; + + // Level 6. -------------------------------------------------------------------- + + QString URI_AUTHORITY = "(?:" + URI_USERINFO + "@" + ")?" + + URI_HOST + + "(?:" + ":" + URI_PORT + ")?"; + + QString IRI_AUTHORITY = "(?:" + IRI_USERINFO + "@" + ")?" + + IRI_HOST + + "(?:" + ":" + URI_PORT + ")?"; + + // Level 7. -------------------------------------------------------------------- + + // `path-empty` not used. + QString URI_HIER_PART = QString("(?:") + + "//" + URI_AUTHORITY + URI_PATH_ABEMPTY + + "|" + URI_PATH_ABSOLUTE + + "|" + URI_PATH_ROOTLESS + + ")"; + QString IRI_HIER_PART = QString("(?:") + + "//" + IRI_AUTHORITY + IRI_PATH_ABEMPTY + + "|" + IRI_PATH_ABSOLUTE + + "|" + IRI_PATH_ROOTLESS + + ")"; + + // Level 8. -------------------------------------------------------------------- + + // Regex to match URI. It respects the RFC 3986. + QString URI = "(?:" + + URI_SCHEME + ":" + "|" + "www\\." + ")" + + URI_HIER_PART + "(?:" + "\\?" + URI_QUERY + ")?" + + "(?:" + "#" + URI_FRAGMENT + ")?"; + + // Regex to match URI. It respects the RFC 3987. + QString IRI = "(?:" + URI_SCHEME + ":" + "|" + "www\\." + ")" + + IRI_HIER_PART + "(?:" + "\\?" + IRI_QUERY + ")?" + + "(?:" + "#" + IRI_FRAGMENT + ")?"; + + mIriRegularExpression = QRegularExpression(IRI,QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption); + mUriRegularExpression = QRegularExpression(URI,QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption); +} diff --git a/linphone-app/src/utils/UriTools.hpp b/linphone-app/src/utils/UriTools.hpp new file mode 100644 index 000000000..30859268d --- /dev/null +++ b/linphone-app/src/utils/UriTools.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010-2023 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +// ============================================================================= +// Library to deal with IRI and URI. +// See: +// IRI : https://tools.ietf.org/html/rfc3987 +// NOTE : Unicodes after \uFFFF are not supported by the QML RegExp (or the right syntax has not been found) : "Invalid regular expression" (even with surrogate pairs). Parts have been commented out for latter use. +// URI : https://tools.ietf.org/html/rfc3986 +// ============================================================================= + + +#ifndef URI_TOOLS_H +#define URI_TOOLS_H + +#include +#include +#include +#include + +class UriTools{ +public: + UriTools(); + bool mSupportUrl = true; + + + static QVector > parseIri(const QString& text); + static QVector > parseUri(const QString& text); + static QRegularExpression getRegularExpression(); + +private: + void initRegularExpressions(); + static QVector > parse(const QString& text, const QRegularExpression regex); + + QRegularExpression mIriRegularExpression;//https://tools.ietf.org/html/rfc3987 + QRegularExpression mUriRegularExpression;//https://tools.ietf.org/html/rfc3986 +}; + + + +#endif \ No newline at end of file diff --git a/linphone-app/src/utils/Utils.cpp b/linphone-app/src/utils/Utils.cpp index 1ff0e0351..5b8cf8025 100644 --- a/linphone-app/src/utils/Utils.cpp +++ b/linphone-app/src/utils/Utils.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "Utils.hpp" +#include "UriTools.hpp" #include "components/core/CoreManager.hpp" #include "components/contacts/ContactsListModel.hpp" #include "components/contact/ContactModel.hpp" @@ -604,4 +605,46 @@ QString Utils::getFileChecksum(const QString& filePath){ } } return QString(); +} + +QString Utils::encodeTextToQmlRichFormat(const QString& text, const QVariantMap& options){ + + QString images; + QStringList formattedText; + QStringList imageFormat; + for(auto format : QImageReader::supportedImageFormats()) + imageFormat.append(QString::fromLatin1(format).toUpper()); + auto iriParsed = UriTools::parseIri(text); + for(int i = 0 ; i < iriParsed.size() ; ++i){ + QString iri = iriParsed[i].second.replace('&', "&") + .replace('<', "\u2063<") + .replace('>', "\u2063>") + .replace('"', """) + .replace('\'', "'"); + if(!iriParsed[i].first) + formattedText.append(iri); + else{ + QString uri = iriParsed[i].second.left(3) == "www" ? "http://"+iriParsed[i].second : iriParsed[i].second ; + int extIndex = iriParsed[i].second.lastIndexOf('.'); + QString ext; + if( extIndex >= 0) + ext = iriParsed[i].second.mid(extIndex+1).toUpper(); + if(imageFormat.contains(ext.toLatin1())){// imagesHeight is not used because of bugs on display (blank image if set without width) + images += ""; + }else + formattedText.append( "" + iri + ""); + } + } + if(images != "") + images = "
" + images +"
"; + + return images + "

" + formattedText.join("") + "

"; } \ No newline at end of file diff --git a/linphone-app/src/utils/Utils.hpp b/linphone-app/src/utils/Utils.hpp index 3a435a297..8c8fcc8b5 100644 --- a/linphone-app/src/utils/Utils.hpp +++ b/linphone-app/src/utils/Utils.hpp @@ -66,6 +66,7 @@ public: Q_INVOKABLE QSize getImageSize(const QString& url); Q_INVOKABLE static QPoint getCursorPosition(); Q_INVOKABLE static QString getFileChecksum(const QString& filePath); + Q_INVOKABLE static QString encodeTextToQmlRichFormat(const QString& text, const QVariantMap& options); //---------------------------------------------------------------------------------- diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatTextMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatTextMessage.qml index a3cc6428a..794e63cab 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatTextMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatTextMessage.qml @@ -42,7 +42,7 @@ TextEdit { font.family: customFont.family font.pointSize: Units.dp * customFont.pointSize - text: visible ? Utils.encodeTextToQmlRichFormat(contentModel.text, { + text: visible ? UtilsCpp.encodeTextToQmlRichFormat(contentModel.text, { imagesHeight: ChatStyle.entry.message.images.height, imagesWidth: ChatStyle.entry.message.images.width }) diff --git a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml index 5027e8946..07bda7f80 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatStyle.qml @@ -243,7 +243,8 @@ QtObject { } property QtObject images: QtObject { - property int height: 48 + property int height: 240 + property int width: 240 } property QtObject incoming: QtObject { diff --git a/linphone-app/ui/scripts/Utils/uri-tools.js b/linphone-app/ui/scripts/Utils/uri-tools.js deleted file mode 100644 index b32941cd4..000000000 --- a/linphone-app/ui/scripts/Utils/uri-tools.js +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2010-2020 Belledonne Communications SARL. - * - * This file is part of linphone-desktop - * (see https://www.linphone.org). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -// ============================================================================= -// Library to deal with URI. -// See: https://tools.ietf.org/html/rfc3986#section-1.3 -// ============================================================================= - -.pragma library - -// Options. - -// If true, strings starting with `www.` can be detected. -// Not standard but helpful. -var SUPPORTS_URL = true - -// Level 0. -------------------------------------------------------------------- - -var URI_DEC_OCTET = '(?:' + - '25[0-5]' + - '|' + '2[0-4]\\d' + - '|' + '1\\d{2}' + - '|' + '[1-9]\\d' + - '|' + '\\d' + -')' - -var URI_H16 = '[0-9A-Fa-f]{1,4}' -var URI_PCT_ENCODED = '%[A-Fa-f\\d]{2}' -var URI_PORT = '\\d*' -var URI_SCHEME = '[a-zA-Z][\\w+\-\.]*' -var URI_SUB_DELIMS = '[!$&\'()*+,;=]' -var URI_UNRESERVED = '[\\w\-\._~]' - -// Level 1. -------------------------------------------------------------------- - -var URI_IPV_FUTURE = 'v[0-9A-Fa-f]+\\.' + '(?:' + - URI_UNRESERVED + - URI_SUB_DELIMS + - ':' + -')' - -var URI_IPV4_ADDRESS = URI_DEC_OCTET + '\\.' + URI_DEC_OCTET + '\\.' + - URI_DEC_OCTET + '\\.' + URI_DEC_OCTET - -var URI_PCHAR = '(?:' + - URI_UNRESERVED + - '|' + URI_PCT_ENCODED + - '|' + URI_SUB_DELIMS + - '|' + '[:@]' + -')' - -var URI_REG_NAME = '(?:' + - URI_UNRESERVED + - '|' + URI_PCT_ENCODED + - '|' + URI_SUB_DELIMS + -')*' - -var URI_USERINFO = '(?:' + - URI_UNRESERVED + - '|' + URI_PCT_ENCODED + - '|' + URI_SUB_DELIMS + - '|' + ':' + -')*' - -// Level 2. -------------------------------------------------------------------- - -var URI_FRAGMENT = '(?:' + - URI_PCHAR + - '|' + '[/?]' + -')*' - -var URI_LS32 = '(?:' + - URI_H16 + ':' + URI_H16 + - '|' + URI_IPV4_ADDRESS + -')' - -var URI_QUERY = '(?:' + - URI_PCHAR + - '|' + '[/?]' + -')*' - -var URI_SEGMENT = URI_PCHAR + '*' -var URI_SEGMENT_NZ = URI_PCHAR + '+' - -// Level 3. -------------------------------------------------------------------- - -var URI_IPV6_ADDRESS = '(?:' + - '(?:' + URI_H16 + ':){6}' + URI_LS32 + - '|' + '::(?:' + URI_H16 + ':){5}' + URI_LS32 + - '|' + '\\[' + URI_H16 + '\\]::(?:' + URI_H16 + ':){4}' + URI_LS32 + - '|' + '\\[' + '(?:' + URI_H16 + ':)?' + URI_H16 + '\\]::(?:' + URI_H16 + ':){3}' + URI_LS32 + - '|' + '\\[' + '(?:' + URI_H16 + ':){0,2}' + URI_H16 + '\\]::(?:' + URI_H16 + ':){2}' + URI_LS32 + - '|' + '\\[' + '(?:' + URI_H16 + ':){0,3}' + URI_H16 + '\\]::' + URI_H16 + ':' + URI_LS32 + - '|' + '\\[' + '(?:' + URI_H16 + ':){0,4}' + URI_H16 + '\\]::' + URI_LS32 + - '|' + '\\[' + '(?:' + URI_H16 + ':){0,5}' + URI_H16 + '\\]::' + URI_H16 + - '|' + '\\[' + '(?:' + URI_H16 + ':){0,6}' + URI_H16 + '\\]::' + -')' - -var URI_PATH_ABEMPTY = '(?:' + '/' + URI_SEGMENT + ')*' - -var URI_PATH_ABSOLUTE = '/' + - '(?:' + URI_SEGMENT_NZ + '(?:' + '/' + URI_SEGMENT + ')*' + ')?' - -var URI_PATH_ROOTLESS = - URI_SEGMENT_NZ + '(?:' + '/' + URI_SEGMENT + ')*' - -// Level 4. -------------------------------------------------------------------- - -var URI_IP_LITERAL = '\\[' + - '(?:' + - URI_IPV6_ADDRESS + - '|' + URI_IPV_FUTURE + - ')' + -'\\]' - -// Level 5. -------------------------------------------------------------------- - -var URI_HOST = '(?:' + - URI_REG_NAME + - '|' + URI_IPV4_ADDRESS + - '|' + URI_IP_LITERAL + -')' - -// Level 6. -------------------------------------------------------------------- - -var URI_AUTHORITY = '(?:' + URI_USERINFO + '@' + ')?' + - URI_HOST + - '(?:' + ':' + URI_PORT + ')?' - -// Level 7. -------------------------------------------------------------------- - -// `path-empty` not used. -var URI_HIER_PART = '(?:' + - '//' + URI_AUTHORITY + URI_PATH_ABEMPTY + - '|' + URI_PATH_ABSOLUTE + - '|' + URI_PATH_ROOTLESS + -')' - -// Level 8. -------------------------------------------------------------------- - -// Regex to match URI. It respects the RFC 3986. -var URI = (SUPPORTS_URL - ? '(?:' + URI_SCHEME + ':' + '|' + 'www\\.' + ')' - : URI_SCHEME + ':' -) + URI_HIER_PART + '(?:' + '\\?' + URI_QUERY + ')?' + - '(?:' + '#' + URI_FRAGMENT + ')?' - -var URI_REGEX = new RegExp('(' + URI + ')', 'g') diff --git a/linphone-app/ui/scripts/Utils/utils.js b/linphone-app/ui/scripts/Utils/utils.js index 3b8c80bc8..d4a0e1132 100644 --- a/linphone-app/ui/scripts/Utils/utils.js +++ b/linphone-app/ui/scripts/Utils/utils.js @@ -27,7 +27,6 @@ .import Linphone 1.0 as Linphone .import 'port-tools.js' as PortTools -.import 'uri-tools.js' as UriTools // ============================================================================= // Constants. @@ -97,51 +96,6 @@ function createObject (source, parent, options) { // ----------------------------------------------------------------------------- -function encodeTextToQmlRichFormat (text, options) { - var images = '' - - if (!options) { - options = {} - } - - var formattedText = execAll(UriTools.URI_REGEX, text, function (str, valid) { - if (!valid) { - return unscapeHtml(str) - } - - var uri = startsWith(str, 'www.') ? 'http://' + str : str - - var ext = getExtension(str) - if (includes([ 'jpg', 'jpeg', 'gif', 'png', 'svg' ], ext)) { - images += '' - } - - return '' + unscapeHtml(str) + '' - }).join('') - if (images.length > 0) { - images = '
' + images + '
' - } - - return images.concat('

' + formattedText + '

') -} - -function extractFirstUri (str) { - var res = str.match(UriTools.URI_REGEX) - return res == null || startsWith(res[0], 'www') - ? undefined - : res[0] -} - -// ----------------------------------------------------------------------------- - function getSystemPathFromUri (uri) { var str = uri.toString() if (startsWith(str, 'file://')) { @@ -385,40 +339,6 @@ function dirname (str) { // ----------------------------------------------------------------------------- -function execAll (regex, text, cb) { - var index = 0 - var arr = [] - var match - - if (!cb) { - cb = function (text) { - return text - } - } - - while ((match = regex.exec(text))) { - var curIndex = match.index - var matchStr = match[0] - - if (curIndex > index) { - arr.push(cb(text.substring(index, curIndex), false)) - } - - arr.push(cb(matchStr, true)) - - index = curIndex + matchStr.length - } - - var length = text.length - if (index < length) { - arr.push(cb(text.substring(index, length))) - } - - return arr -} - -// ----------------------------------------------------------------------------- - function extractProperties (obj, pattern) { if (!pattern) { return {}