diff options
| author | Linus Jahn <lnj@kaidan.im> | 2023-04-07 16:21:10 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2023-04-07 16:21:10 +0200 |
| commit | ab4bdf2da41a26f462fe3a333a34e32c999e2a6d (patch) | |
| tree | 2501bde9b6da885056166c769befa7f7d4729e49 | |
| parent | c8e13f6fd3df8dcab0170dda6f54eaf5175d8437 (diff) | |
| parent | b44a7ee310bd2c9bc7c0d234ab7a96c501d20559 (diff) | |
Merge branch '1.5'
26 files changed, 279 insertions, 164 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 55f4ef97..3516f0e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,20 @@ QXmpp 1.6.0 (UNRELEASED) *under development* +QXmpp 1.5.4 (Apr 07, 2023) +-------------------------- + +Fixes: + - OMEMO fixes (@melvo) + - Fix use-after-move in EntityTimeManager (@lnjX) + - EME: Always send encryption name text (@melvo) + - Fix interpretation of empty to/from address in the client (@lnjX) + - MSVC related build fixes (@JBBgameich) + +Misc: + - Support installing QXmpp with Qt 5 and Qt 6 in parallel (@lnjX) + - Support building QXmppOmemo statically (@lnjX) + QXmpp 1.5.3 (Mar 11, 2023) -------------------------- diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f9181f9..f3e3ad94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,12 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/modules") +# Qt if(NOT DEFINED QT_VERSION_MAJOR) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Network Xml) endif() @@ -26,9 +30,6 @@ if(${QT_VERSION_MAJOR} EQUAL 6) find_package(Qt6Core5Compat) endif() -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - include(GNUInstallDirs) option(BUILD_SHARED "Build shared library" ON) @@ -40,6 +41,9 @@ option(BUILD_OMEMO "Build the OMEMO module" OFF) option(WITH_GSTREAMER "Build with GStreamer support for Jingle" OFF) option(WITH_QCA "Build with QCA for OMEMO or encrypted file sharing" ${Qca-qt${QT_VERSION_MAJOR}_FOUND}) +set(QXMPP_TARGET QXmppQt${QT_VERSION_MAJOR}) +set(QXMPPOMEMO_TARGET QXmppOmemoQt${QT_VERSION_MAJOR}) + add_definitions( -DQT_DISABLE_DEPRECATED_BEFORE=0x050F00 -DQURL_NO_CAST_FROM_STRING @@ -82,30 +86,60 @@ endif() include(CMakePackageConfigHelpers) +# Normal QXmppQt5/6 package configure_package_config_file( QXmppConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/QXmppConfig.cmake - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/qxmpp" + ${CMAKE_CURRENT_BINARY_DIR}/${QXMPP_TARGET}Config.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${QXMPP_TARGET}" ) write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/QXmppConfigVersion.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${QXMPP_TARGET}ConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${QXMPP_TARGET}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${QXMPP_TARGET}ConfigVersion.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${QXMPP_TARGET}" + COMPONENT Devel +) + +# QXmpp package with Qt version autodetect +configure_package_config_file( + cmake/QXmppQtAutoConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/QXmppConfig.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/QXmpp" +) + +install( FILES ${CMAKE_CURRENT_BINARY_DIR}/QXmppConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/QXmppConfigVersion.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/qxmpp" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/QXmpp" + COMPONENT Devel +) +install( + FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/QXmppQtAutoConfigVersion.cmake + RENAME QXmppConfigVersion.cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/QXmpp" COMPONENT Devel ) -# Generate qxmpp.pc +# Generate QXmppQt5/6.pc configure_file(${CMAKE_CURRENT_SOURCE_DIR}/qxmpp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/qxmpp.pc @ONLY) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/qxmpp.pc + RENAME QXmppQt${QT_VERSION_MAJOR}.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" COMPONENT Devel ) +# "qxmpp.pc" for backwards-compatibility +if(QT_VERSION_MAJOR EQUAL 5) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/qxmpp.pc + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" + COMPONENT Devel + ) +endif() + diff --git a/QXmppConfig.cmake.in b/QXmppConfig.cmake.in index 2d2303cf..4fae49ec 100644 --- a/QXmppConfig.cmake.in +++ b/QXmppConfig.cmake.in @@ -5,11 +5,11 @@ @PACKAGE_INIT@ set(_QXmpp_FIND_PARTS_REQUIRED) -if(QXmpp_FIND_REQUIRED) +if(QXmppQt@QT_VERSION_MAJOR@_FIND_REQUIRED) set(_QXmpp_FIND_PARTS_REQUIRED REQUIRED) endif() set(_QXmpp_FIND_PARTS_QUIET) -if(QXmpp_FIND_QUIETLY) +if(QXmppQt@QT_VERSION_MAJOR@_FIND_QUIETLY) set(_QXmpp_FIND_PARTS_QUIET QUIET) endif() @@ -20,13 +20,13 @@ find_dependency(Qt@QT_VERSION_MAJOR@Xml) include("${CMAKE_CURRENT_LIST_DIR}/QXmpp.cmake") -foreach(module ${QXmpp_FIND_COMPONENTS}) - find_package(QXmpp${module} - ${QXmpp_FIND_VERSION} +foreach(module ${QXmppQt@QT_VERSION_MAJOR@_FIND_COMPONENTS}) + find_package(QXmpp${module}Qt@QT_VERSION_MAJOR@ + ${QXmppQt@QT_VERSION_MAJOR@_FIND_VERSION} ${_QXmpp_FIND_PARTS_REQUIRED} ${_QXmpp_FIND_PARTS_QUIET} ) - set(QXmpp_${module}_FOUND ${QXmpp${module}_FOUND}) + set(QXmppQt@QT_VERSION_MAJOR@_${module}_FOUND ${QXmpp${module}Qt@QT_VERSION_MAJOR@_FOUND}) endforeach() check_required_components(QXmpp) diff --git a/cmake/QXmppQtAutoConfig.cmake.in b/cmake/QXmppQtAutoConfig.cmake.in new file mode 100644 index 00000000..58c99a96 --- /dev/null +++ b/cmake/QXmppQtAutoConfig.cmake.in @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2023 Linus Jahn <lnj@kaidan.im> +# +# SPDX-License-Identifier: CC0-1.0 + +@PACKAGE_INIT@ + +# Detect Qt version +if(NOT DEFINED QT_VERSION_MAJOR) + if(TARGET Qt6::Core) + set(QT_VERSION_MAJOR 6) + elseif(TARGET Qt5::Core) + set(QT_VERSION_MAJOR 5) + else() + # default to Qt 6 + set(QT_VERSION_MAJOR 6) + endif() +endif() + +set(_QXmpp_FIND_PARTS_REQUIRED) +if(QXmpp_FIND_REQUIRED) + set(_QXmpp_FIND_PARTS_REQUIRED REQUIRED) +endif() +set(_QXmpp_FIND_PARTS_QUIET) +if(QXmpp_FIND_QUIETLY) + set(_QXmpp_FIND_PARTS_QUIET QUIET) +endif() + +# Pass through arguments to QXmppQt5/6 +include(CMakeFindDependencyMacro) +find_package(QXmppQt${QT_VERSION_MAJOR} + ${QXmpp_FIND_VERSION} + ${_QXmpp_FIND_PARTS_REQUIRED} + ${_QXmpp_FIND_PARTS_QUIET} + COMPONENTS ${QXmpp_FIND_COMPONENTS} +) + +set(QXmpp_FOUND ${QXmppQt${QT_VERSION_MAJOR}_FOUND}) diff --git a/cmake/QXmppQtAutoConfigVersion.cmake b/cmake/QXmppQtAutoConfigVersion.cmake new file mode 100644 index 00000000..5f2b3f10 --- /dev/null +++ b/cmake/QXmppQtAutoConfigVersion.cmake @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2023 Linus Jahn <lnj@kaidan.im> +# +# SPDX-License-Identifier: CC0-1.0 + +set(PACKAGE_VERSION "") +# Allow all requested versions here, the actual check is going to be done in QXmppQt5/6. +set(PACKAGE_VERSION_COMPATIBLE TRUE) + diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 41489cef..2500dd2d 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -7,7 +7,6 @@ PROJECT_NUMBER = "Version: @PROJECT_VERSION@" INPUT = @PROJECT_SOURCE_DIR@/doc/index.doc \ @PROJECT_SOURCE_DIR@/doc/using.doc \ @PROJECT_SOURCE_DIR@/doc/xep.doc \ - @CMAKE_BINARY_DIR@/src/base/QXmppBuildConstants.h \ @PROJECT_SOURCE_DIR@/src HTML_EXTRA_FILES = @PROJECT_SOURCE_DIR@/doc/doap.xml \ @PROJECT_SOURCE_DIR@/doc/doap-rendering/doap.xsl \ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 0a1de8a2..8f83ce27 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,7 +4,7 @@ macro(add_simple_example EXAMPLE_NAME) add_executable(${EXAMPLE_NAME} example_${EXAMPLE_NAME}/example_${EXAMPLE_NAME}.cpp) - target_link_libraries(${EXAMPLE_NAME} qxmpp) + target_link_libraries(${EXAMPLE_NAME} ${QXMPP_TARGET}) endmacro() include_directories(${PROJECT_SOURCE_DIR}/src/base) diff --git a/examples/example_5_rpcInterface/CMakeLists.txt b/examples/example_5_rpcInterface/CMakeLists.txt index c58fdc40..b18299ad 100644 --- a/examples/example_5_rpcInterface/CMakeLists.txt +++ b/examples/example_5_rpcInterface/CMakeLists.txt @@ -3,4 +3,4 @@ # SPDX-License-Identifier: CC0-1.0 add_executable(5_rpcInterface main.cpp remoteinterface.cpp) -target_link_libraries(5_rpcInterface qxmpp) +target_link_libraries(5_rpcInterface ${QXMPP_TARGET}) diff --git a/examples/example_6_rpcClient/CMakeLists.txt b/examples/example_6_rpcClient/CMakeLists.txt index 2c19a92c..8ad4de2e 100644 --- a/examples/example_6_rpcClient/CMakeLists.txt +++ b/examples/example_6_rpcClient/CMakeLists.txt @@ -3,4 +3,4 @@ # SPDX-License-Identifier: CC0-1.0 add_executable(6_rpcClient main.cpp rpcClient.cpp) -target_link_libraries(6_rpcClient qxmpp) +target_link_libraries(6_rpcClient ${QXMPP_TARGET}) diff --git a/examples/example_9_vCard/CMakeLists.txt b/examples/example_9_vCard/CMakeLists.txt index 2fc4ba63..d187f9f6 100644 --- a/examples/example_9_vCard/CMakeLists.txt +++ b/examples/example_9_vCard/CMakeLists.txt @@ -5,4 +5,4 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Gui) add_executable(9_vCard example_9_vCard.cpp) -target_link_libraries(9_vCard Qt${QT_VERSION_MAJOR}::Gui qxmpp) +target_link_libraries(9_vCard Qt${QT_VERSION_MAJOR}::Gui ${QXMPP_TARGET}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 82e99619..929554c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -276,28 +276,28 @@ set(SOURCE_FILES ) if(BUILD_SHARED) - add_library(qxmpp SHARED ${SOURCE_FILES}) + add_library(${QXMPP_TARGET} SHARED ${SOURCE_FILES}) else() - add_library(qxmpp STATIC ${SOURCE_FILES}) + add_library(${QXMPP_TARGET} STATIC ${SOURCE_FILES}) endif() -set_target_properties(qxmpp PROPERTIES +set_target_properties(${QXMPP_TARGET} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${SO_VERSION} EXPORT_NAME QXmpp ) -target_include_directories(qxmpp +target_include_directories(${QXMPP_TARGET} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/base> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/client> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/server> - $<INSTALL_INTERFACE:include/qxmpp> + $<INSTALL_INTERFACE:include/${QXMPP_TARGET}> PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) -target_link_libraries(qxmpp +target_link_libraries(${QXMPP_TARGET} PUBLIC Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network @@ -316,21 +316,21 @@ if(WITH_GSTREAMER) client/QXmppCallStream.h ) - target_sources(qxmpp + target_sources(${QXMPP_TARGET} PRIVATE client/QXmppCall.cpp client/QXmppCallManager.cpp client/QXmppCallStream.cpp ) - target_link_libraries(qxmpp + target_link_libraries(${QXMPP_TARGET} PRIVATE ${GLIB2_LIBRARIES} ${GOBJECT_LIBRARIES} ${GSTREAMER_LIBRARY} ) - target_include_directories(qxmpp + target_include_directories(${QXMPP_TARGET} PRIVATE ${GLIB2_INCLUDE_DIR} ${GOBJECT_INCLUDE_DIR} @@ -340,13 +340,13 @@ endif() if(BUILD_OMEMO) # required to be used in QXmppMessage - target_sources(qxmpp PRIVATE base/QXmppOmemoDataBase.cpp) + target_sources(${QXMPP_TARGET} PRIVATE base/QXmppOmemoDataBase.cpp) endif() if(WITH_QCA) - target_sources(qxmpp PRIVATE client/QXmppEncryptedFileSharingProvider.cpp client/QXmppFileEncryption.cpp client/QcaInitializer.cpp) + target_sources(${QXMPP_TARGET} PRIVATE client/QXmppEncryptedFileSharingProvider.cpp client/QXmppFileEncryption.cpp client/QcaInitializer.cpp) set(INSTALL_HEADER_FILES ${INSTALL_HEADER_FILES} client/QXmppEncryptedFileSharingProvider.h) - target_link_libraries(qxmpp PRIVATE qca-qt${QT_VERSION_MAJOR}) + target_link_libraries(${QXMPP_TARGET} PRIVATE qca-qt${QT_VERSION_MAJOR}) endif() # qxmpp_export.h generation @@ -363,12 +363,13 @@ set(QXMPP_CUSTOM_EXPORT_CONTENT " #define QXMPP_VERSION_PATCH ${PROJECT_VERSION_PATCH} ") -generate_export_header(qxmpp +generate_export_header(${QXMPP_TARGET} + BASE_NAME qxmpp CUSTOM_CONTENT_FROM_VARIABLE QXMPP_CUSTOM_EXPORT_CONTENT ) install( - TARGETS qxmpp + TARGETS ${QXMPP_TARGET} EXPORT QXmppTarget RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -377,20 +378,20 @@ install( install( EXPORT QXmppTarget - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/qxmpp" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${QXMPP_TARGET}" FILE QXmpp.cmake NAMESPACE QXmpp:: COMPONENT Devel ) export( - TARGETS qxmpp + TARGETS ${QXMPP_TARGET} FILE QXmpp.cmake ) install( FILES ${INSTALL_HEADER_FILES} ${CMAKE_CURRENT_BINARY_DIR}/qxmpp_export.h - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/qxmpp" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QXMPP_TARGET}" ) # submodules diff --git a/src/base/QXmppMamIq.h b/src/base/QXmppMamIq.h index 6a1df144..78d5c77a 100644 --- a/src/base/QXmppMamIq.h +++ b/src/base/QXmppMamIq.h @@ -14,7 +14,7 @@ class QXmppMamQueryIqPrivate; class QXmppMamResultIqPrivate; -class QXmppMamQueryIq : public QXmppIq +class QXMPP_EXPORT QXmppMamQueryIq : public QXmppIq { public: QXmppMamQueryIq(); @@ -46,7 +46,7 @@ private: QSharedDataPointer<QXmppMamQueryIqPrivate> d; }; -class QXmppMamResultIq : public QXmppIq +class QXMPP_EXPORT QXmppMamResultIq : public QXmppIq { public: QXmppMamResultIq(); diff --git a/src/base/QXmppPubSubIq_p.h b/src/base/QXmppPubSubIq_p.h index c8828579..0ff1de04 100644 --- a/src/base/QXmppPubSubIq_p.h +++ b/src/base/QXmppPubSubIq_p.h @@ -152,7 +152,7 @@ void PubSubIq<T>::parseItems(const QDomElement &queryElement) childElement = childElement.nextSiblingElement(QStringLiteral("item"))) { T item; item.parse(childElement); - m_items << std::move(item); + m_items.push_back(std::move(item)); } } diff --git a/src/client/QXmppMamManager.cpp b/src/client/QXmppMamManager.cpp index fe0735c7..046f01b0 100644 --- a/src/client/QXmppMamManager.cpp +++ b/src/client/QXmppMamManager.cpp @@ -339,7 +339,8 @@ QXmppTask<QXmppMamManager::RetrieveResult> QXmppMamManager::retrieveMessages(con // because some decryptMessage() jobs could finish instantly state.runningDecryptionJobs = encryptedCount; - for (auto i = 0; i < state.messages.size(); i++) { + int size = state.messages.size(); + for (auto i = 0; i < size; i++) { if (!messagesEncrypted[i]) { continue; } diff --git a/src/client/QXmppMamManager.h b/src/client/QXmppMamManager.h index 71cb4311..548d56d6 100644 --- a/src/client/QXmppMamManager.h +++ b/src/client/QXmppMamManager.h @@ -40,7 +40,7 @@ class QXMPP_EXPORT QXmppMamManager : public QXmppClientExtension Q_OBJECT public: - struct RetrievedMessages + struct QXMPP_EXPORT RetrievedMessages { QXmppMamResultIq result; QVector<QXmppMessage> messages; diff --git a/src/omemo/CMakeLists.txt b/src/omemo/CMakeLists.txt index 89e1f06c..9086ec64 100644 --- a/src/omemo/CMakeLists.txt +++ b/src/omemo/CMakeLists.txt @@ -4,8 +4,8 @@ include(CMakePackageConfigHelpers) -set(OMEMO_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/QXmppOmemo") -set(OMEMO_HEADER_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/qxmpp/omemo") +set(OMEMO_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${QXMPPOMEMO_TARGET}") +set(OMEMO_HEADER_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/${QXMPP_TARGET}/Omemo") set(OMEMO_INSTALL_HEADER_FILES QXmppOmemoManager.h QXmppOmemoMemoryStorage.h @@ -20,17 +20,21 @@ set(OMEMO_SOURCE_FILES QXmppOmemoStorage.cpp ) -add_library(QXmppOmemo SHARED ${OMEMO_SOURCE_FILES}) +if(BUILD_SHARED) + add_library(${QXMPPOMEMO_TARGET} SHARED ${OMEMO_SOURCE_FILES}) +else() + add_library(${QXMPPOMEMO_TARGET} STATIC ${OMEMO_SOURCE_FILES}) +endif() -target_link_libraries(QXmppOmemo +target_link_libraries(${QXMPPOMEMO_TARGET} PUBLIC - qxmpp + ${QXMPP_TARGET} Qt${QT_VERSION_MAJOR}::Core PRIVATE PkgConfig::OmemoC qca-qt${QT_VERSION_MAJOR} ) -target_include_directories(QXmppOmemo +target_include_directories(${QXMPPOMEMO_TARGET} PUBLIC ${OMEMO_HEADER_DIR} PRIVATE @@ -39,21 +43,21 @@ target_include_directories(QXmppOmemo ${PROJECT_BINARY_DIR}/src ) -generate_export_header(QXmppOmemo) +generate_export_header(${QXMPPOMEMO_TARGET} BASE_NAME qxmppomemo) install( FILES ${OMEMO_INSTALL_HEADER_FILES} ${CMAKE_CURRENT_BINARY_DIR}/qxmppomemo_export.h DESTINATION ${OMEMO_HEADER_DIR} ) -set_target_properties(QXmppOmemo PROPERTIES +set_target_properties(${QXMPPOMEMO_TARGET} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${SO_VERSION} EXPORT_NAME Omemo ) install( - TARGETS QXmppOmemo + TARGETS ${QXMPPOMEMO_TARGET} EXPORT QXmppOmemoTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -69,25 +73,25 @@ install( ) export( - TARGETS QXmppOmemo + TARGETS ${QXMPPOMEMO_TARGET} FILE QXmppOmemo.cmake ) configure_package_config_file( QXmppOmemoConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/QXmppOmemoConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${QXMPPOMEMO_TARGET}Config.cmake INSTALL_DESTINATION ${OMEMO_CMAKE_DIR} ) write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/QXmppOmemoConfigVersion.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${QXMPPOMEMO_TARGET}ConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/QXmppOmemoConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/QXmppOmemoConfigVersion.cmake + FILES ${CMAKE_CURRENT_BINARY_DIR}/${QXMPPOMEMO_TARGET}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${QXMPPOMEMO_TARGET}ConfigVersion.cmake DESTINATION ${OMEMO_CMAKE_DIR} COMPONENT Devel ) diff --git a/src/omemo/QXmppOmemoConfig.cmake.in b/src/omemo/QXmppOmemoConfig.cmake.in index 5363c0f5..68596637 100644 --- a/src/omemo/QXmppOmemoConfig.cmake.in +++ b/src/omemo/QXmppOmemoConfig.cmake.in @@ -5,8 +5,8 @@ @PACKAGE_INIT@ include(CMakeFindDependencyMacro) -find_dependency(QXmpp) +find_dependency(QXmppQt@QT_VERSION_MAJOR@) include("${CMAKE_CURRENT_LIST_DIR}/QXmppOmemo.cmake") -check_required_components(QXmppOmemo) +check_required_components(QXmppOmemoQt@QT_VERSION_MAJOR@) diff --git a/src/omemo/QXmppOmemoData.cpp b/src/omemo/QXmppOmemoData.cpp index 43e00c35..220e628f 100644 --- a/src/omemo/QXmppOmemoData.cpp +++ b/src/omemo/QXmppOmemoData.cpp @@ -13,7 +13,7 @@ #include <QDomElement> #include <QHash> -const char *ns_omemo_2 = "urn:xmpp:omemo:2"; +constexpr auto ns_omemo_2 = "urn:xmpp:omemo:2"; /// \cond /// diff --git a/src/omemo/QXmppOmemoManager.cpp b/src/omemo/QXmppOmemoManager.cpp index a3ad12bb..f9172d3b 100644 --- a/src/omemo/QXmppOmemoManager.cpp +++ b/src/omemo/QXmppOmemoManager.cpp @@ -675,11 +675,13 @@ QXmppOmemoOwnDevice Manager::ownDevice() /// Returns all locally stored devices except the own device. /// -/// Only devices that have been received after subscribing the corresponding -/// device lists on the server are stored locally. +/// Only devices that have been received after subscribing the corresponding device lists on the +/// server are stored locally. /// Thus, only those are returned. -/// Call \c QXmppOmemoManager::subscribeToDeviceLists() for contacts without -/// presence subscription before. +/// Call \c QXmppOmemoManager::subscribeToDeviceLists() for contacts without presence subscription +/// before. +/// +/// You must build sessions before you can get devices with corresponding keys. /// /// /\return all devices except the own device /// @@ -691,11 +693,13 @@ QXmppTask<QVector<QXmppOmemoDevice>> Manager::devices() /// /// Returns locally stored devices except the own device. /// -/// Only devices that have been received after subscribing the corresponding -/// device lists on the server are stored locally. +/// Only devices that have been received after subscribing the corresponding device lists on the +/// server are stored locally. /// Thus, only those are returned. -/// Call \c QXmppOmemoManager::subscribeToDeviceLists() for contacts without -/// presence subscription before. +/// Call \c QXmppOmemoManager::subscribeToDeviceLists() for contacts without presence subscription +/// before. +/// +/// You must build sessions before you can get devices with corresponding keys. /// /// \param jids JIDs whose devices are being retrieved /// @@ -835,16 +839,15 @@ bool Manager::isNewDeviceAutoSessionBuildingEnabled() /// /// Builds sessions manually with devices for whom no sessions are available. /// -/// Usually, sessions are built during sending a first message to a device or -/// after a first message is received from a device. +/// Usually, sessions are built during sending a first message to a device or after a first message +/// is received from a device. /// This can be called in order to speed up the sending of a message. -/// If this method is called before sending the first message, all sessions can -/// be built and when the first message is sent, the message has only be -/// encrypted. -/// Especially chats with multiple devices, that can decrease the noticeable -/// time a user has to wait for sending a message. -/// Additionally, the keys are automatically retrieved from the server which is -/// helpful in order to get them when calling \c QXmppOmemoManager::devices(). +/// If this method is called before sending the first message, all sessions can be built and when +/// the first message is being sent, the message only needs to be encrypted. +/// Especially for chats with multiple devices, that can decrease the noticeable time a user has to +/// wait for sending a message. +/// Additionally, the keys are automatically retrieved from the server which is helpful in order to +/// get them when calling \c QXmppOmemoManager::devices(). /// /// The user must be logged in while calling this. /// @@ -1240,21 +1243,30 @@ void Manager::setClient(QXmppClient *client) connect(d->trustManager, &QXmppTrustManager::trustLevelsChanged, this, [=](const QHash<QString, QMultiHash<QString, QByteArray>> &modifiedKeys) { const auto &modifiedOmemoKeys = modifiedKeys.value(ns_omemo_2); - Q_EMIT trustLevelsChanged(modifiedOmemoKeys); + + if (!modifiedOmemoKeys.isEmpty()) { + Q_EMIT trustLevelsChanged(modifiedOmemoKeys); + } + + QMultiHash<QString, uint32_t> modifiedDevices; for (auto itr = modifiedOmemoKeys.cbegin(); itr != modifiedOmemoKeys.cend(); ++itr) { const auto &keyOwnerJid = itr.key(); const auto &keyId = itr.value(); - // Emit 'deviceChanged()' only if there is a device with the key. + // Ensure to emit 'deviceChanged()' later only if there is a device with the key. const auto &devices = d->devices.value(keyOwnerJid); - for (auto itr = devices.cbegin(); itr != devices.cend(); ++itr) { - if (itr->keyId == keyId) { - Q_EMIT deviceChanged(keyOwnerJid, itr.key()); - return; + for (auto devicesItr = devices.cbegin(); devicesItr != devices.cend(); ++devicesItr) { + if (devicesItr->keyId == keyId) { + modifiedDevices.insert(keyOwnerJid, devicesItr.key()); + break; } } } + + for (auto modifiedDevicesItr = modifiedDevices.cbegin(); modifiedDevicesItr != modifiedDevices.cend(); ++modifiedDevicesItr) { + Q_EMIT deviceChanged(modifiedDevicesItr.key(), modifiedDevicesItr.value()); + } }); } diff --git a/src/omemo/QXmppOmemoManager_p.cpp b/src/omemo/QXmppOmemoManager_p.cpp index bcfd8303..e8a209ee 100644 --- a/src/omemo/QXmppOmemoManager_p.cpp +++ b/src/omemo/QXmppOmemoManager_p.cpp @@ -35,14 +35,14 @@ using Error = QXmppStanza::Error; using Manager = QXmppOmemoManager; using ManagerPrivate = QXmppOmemoManagerPrivate; -const char *ns_client = "jabber:client"; -const char *ns_pubsub_auto_create = "http://jabber.org/protocol/pubsub#auto-create"; -const char *ns_pubsub_config_node = "http://jabber.org/protocol/pubsub#config-node"; -const char *ns_pubsub_config_node_max = "http://jabber.org/protocol/pubsub#config-node-max"; -const char *ns_pubsub_create_and_configure = "http://jabber.org/protocol/pubsub#create-and-configure"; -const char *ns_pubsub_create_nodes = "http://jabber.org/protocol/pubsub#create-nodes"; -const char *ns_pubsub_publish = "http://jabber.org/protocol/pubsub#publish"; -const char *ns_pubsub_publish_options = "http://jabber.org/protocol/pubsub#publish-options"; +constexpr auto ns_client = "jabber:client"; +constexpr auto ns_pubsub_auto_create = "http://jabber.org/protocol/pubsub#auto-create"; +constexpr auto ns_pubsub_config_node = "http://jabber.org/protocol/pubsub#config-node"; +constexpr auto ns_pubsub_config_node_max = "http://jabber.org/protocol/pubsub#config-node-max"; +constexpr auto ns_pubsub_create_and_configure = "http://jabber.org/protocol/pubsub#create-and-configure"; +constexpr auto ns_pubsub_create_nodes = "http://jabber.org/protocol/pubsub#create-nodes"; +constexpr auto ns_pubsub_publish = "http://jabber.org/protocol/pubsub#publish"; +constexpr auto ns_pubsub_publish_options = "http://jabber.org/protocol/pubsub#publish-options"; namespace QXmpp::Omemo::Private { @@ -754,7 +754,7 @@ void ManagerPrivate::renewSignedPreKeyPairs() if (isSignedPreKeyPairRemoved) { RefCountedPtr<ratchet_identity_key_pair> identityKeyPair; - generateIdentityKeyPair(identityKeyPair.ptrRef()); + deserializeIdentityKeyPair(identityKeyPair.ptrRef()); updateSignedPreKeyPair(identityKeyPair.get()); // Store the own device containing the new signed pre key ID. @@ -960,54 +960,6 @@ void ManagerPrivate::removeDevicesRemovedFromServer() } // -// Generates an identity key pair. -// -// The identity key pair is the pair of private and a public long-term key. -// -// \param identityKeyPair identity key pair location -// -// \return whether it succeeded -// -bool ManagerPrivate::generateIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair) const -{ - BufferSecurePtr privateIdentityKeyBuffer = BufferSecurePtr::fromByteArray(ownDevice.privateIdentityKey); - - if (!privateIdentityKeyBuffer) { - warning("Buffer for serialized private identity key could not be created"); - return false; - } - - RefCountedPtr<ec_private_key> privateIdentityKey; - - if (curve_decode_private_point(privateIdentityKey.ptrRef(), signal_buffer_data(privateIdentityKeyBuffer.get()), signal_buffer_len(privateIdentityKeyBuffer.get()), globalContext.get()) < 0) { - warning("Private identity key could not be deserialized"); - return false; - } - - const auto &serializedPublicIdentityKey = ownDevice.publicIdentityKey; - BufferPtr publicIdentityKeyBuffer = BufferPtr::fromByteArray(serializedPublicIdentityKey); - - if (!publicIdentityKeyBuffer) { - warning("Buffer for serialized public identity key could not be created"); - return false; - } - - RefCountedPtr<ec_public_key> publicIdentityKey; - - if (curve_decode_point_ed(publicIdentityKey.ptrRef(), signal_buffer_data(publicIdentityKeyBuffer.get()), signal_buffer_len(publicIdentityKeyBuffer.get()), globalContext.get()) < 0) { - warning("Public identity key could not be deserialized"); - return false; - } - - if (ratchet_identity_key_pair_create(identityKeyPair, publicIdentityKey.get(), privateIdentityKey.get()) < 0) { - warning("Identity key pair could not be deserialized"); - return false; - } - - return true; -} - -// // Encrypts a message for specific recipients. // // \param message message to be encrypted @@ -1428,15 +1380,14 @@ QByteArray ManagerPrivate::createOmemoEnvelopeData(const signal_protocol_address // QXmppTask<std::optional<QXmppMessage>> ManagerPrivate::decryptMessage(QXmppMessage stanza) { - QXmppPromise<std::optional<QXmppMessage>> interface; - // At this point, the stanza has always an OMEMO element. const auto omemoElement = *stanza.omemoElement(); - if (auto optionalOmemoEnvelope = omemoElement.searchEnvelope(ownBareJid(), ownDevice.id)) { + if (const auto omemoEnvelope = omemoElement.searchEnvelope(ownBareJid(), ownDevice.id)) { + QXmppPromise<std::optional<QXmppMessage>> interface; + const auto senderJid = QXmppUtils::jidToBareJid(stanza.from()); const auto senderDeviceId = omemoElement.senderDeviceId(); - const auto omemoEnvelope = *optionalOmemoEnvelope; const auto omemoPayload = omemoElement.payload(); subscribeToNewDeviceLists(senderJid, senderDeviceId); @@ -1445,7 +1396,7 @@ QXmppTask<std::optional<QXmppMessage>> ManagerPrivate::decryptMessage(QXmppMessa // for it after building the initial session or sent by devices to build a new session // with this device. if (omemoPayload.isEmpty()) { - auto future = extractPayloadDecryptionData(senderJid, senderDeviceId, omemoEnvelope); + auto future = extractPayloadDecryptionData(senderJid, senderDeviceId, *omemoEnvelope); future.then(q, [=](std::optional<QCA::SecureArray> payloadDecryptionData) mutable { if (!payloadDecryptionData) { warning("Empty OMEMO message could not be successfully processed"); @@ -1456,7 +1407,7 @@ QXmppTask<std::optional<QXmppMessage>> ManagerPrivate::decryptMessage(QXmppMessa interface.finish(std::nullopt); }); } else { - auto future = decryptStanza(stanza, senderJid, senderDeviceId, omemoEnvelope, omemoPayload); + auto future = decryptStanza(stanza, senderJid, senderDeviceId, *omemoEnvelope, omemoPayload); future.then(q, [=](std::optional<DecryptionResult> optionalDecryptionResult) mutable { if (optionalDecryptionResult) { const auto decryptionResult = std::move(*optionalDecryptionResult); @@ -1474,9 +1425,11 @@ QXmppTask<std::optional<QXmppMessage>> ManagerPrivate::decryptMessage(QXmppMessa } }); } - } - return interface.task(); + return interface.task(); + } else { + return makeReadyTask<std::optional<QXmppMessage>>(std::nullopt); + } } // @@ -1497,13 +1450,13 @@ QXmppTask<std::optional<IqDecryptionResult>> ManagerPrivate::decryptIq(const QDo iq.parse(iqElement); auto omemoElement = iq.omemoElement(); - if (const auto envelope = omemoElement.searchEnvelope(ownBareJid(), ownDevice.id)) { + if (const auto omemoEnvelope = omemoElement.searchEnvelope(ownBareJid(), ownDevice.id)) { const auto senderJid = QXmppUtils::jidToBareJid(iq.from()); const auto senderDeviceId = omemoElement.senderDeviceId(); subscribeToNewDeviceLists(senderJid, senderDeviceId); - auto future = decryptStanza(iq, senderJid, senderDeviceId, *envelope, omemoElement.payload(), false); + auto future = decryptStanza(iq, senderJid, senderDeviceId, *omemoEnvelope, omemoElement.payload(), false); return chain<Result>(std::move(future), q, [iqElement](auto result) -> Result { if (result) { auto decryptedElement = iqElement.cloneNode(true).toElement(); @@ -2659,7 +2612,7 @@ std::optional<QXmppOmemoDeviceListItem> QXmppOmemoManagerPrivate::updateContactD { if (deviceListItems.size() > 1) { const auto itr = std::find_if(deviceListItems.cbegin(), deviceListItems.cend(), [=](const QXmppOmemoDeviceListItem &item) { - return item.id() == QXmppPubSubManager::Current; + return item.id() == QXmppPubSubManager::standardItemIdToString(QXmppPubSubManager::Current); }); if (itr != deviceListItems.cend()) { @@ -3495,6 +3448,56 @@ bool ManagerPrivate::createSessionBundle(session_pre_key_bundle **sessionBundle, } // +// Deserializes the locally stored identity key pair. +// +// The identity key pair is the pair of private and a public long-term keys. +// +// \param identityKeyPair identity key pair location +// +// \return whether it succeeded +// +bool ManagerPrivate::deserializeIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair) const +{ + RefCountedPtr<ec_private_key> privateIdentityKey; + deserializePrivateIdentityKey(privateIdentityKey.ptrRef(), ownDevice.privateIdentityKey); + + RefCountedPtr<ec_public_key> publicIdentityKey; + deserializePublicIdentityKey(publicIdentityKey.ptrRef(), ownDevice.publicIdentityKey); + + if (ratchet_identity_key_pair_create(identityKeyPair, publicIdentityKey.get(), privateIdentityKey.get()) < 0) { + warning("Identity key pair could not be deserialized"); + return false; + } + + return true; +} + +// +// Deserializes a private identity key. +// +// \param privateIdentityKey private identity key location +// \param serializedPrivateIdentityKey serialized private identity key +// +// \return whether it succeeded +// +bool ManagerPrivate::deserializePrivateIdentityKey(ec_private_key **privateIdentityKey, const QByteArray &serializedPrivateIdentityKey) const +{ + BufferSecurePtr privateIdentityKeyBuffer = BufferSecurePtr::fromByteArray(serializedPrivateIdentityKey); + + if (!privateIdentityKeyBuffer) { + warning("Buffer for serialized private identity key could not be created"); + return false; + } + + if (curve_decode_private_point(privateIdentityKey, signal_buffer_data(privateIdentityKeyBuffer.get()), signal_buffer_len(privateIdentityKeyBuffer.get()), globalContext.get()) < 0) { + warning("Private identity key could not be deserialized"); + return false; + } + + return true; +} + +// // Deserializes a public identity key. // // \param publicIdentityKey public identity key location diff --git a/src/omemo/QXmppOmemoManager_p.h b/src/omemo/QXmppOmemoManager_p.h index 0792bdf2..e1ba6ff1 100644 --- a/src/omemo/QXmppOmemoManager_p.h +++ b/src/omemo/QXmppOmemoManager_p.h @@ -194,7 +194,6 @@ public: bool renewPreKeyPairs(uint32_t keyPairBeingRenewed); bool updatePreKeyPairs(uint32_t count = 1); void removeDevicesRemovedFromServer(); - bool generateIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair) const; QXmppTask<QXmppE2eeExtension::MessageEncryptResult> encryptMessageForRecipients(QXmppMessage &&message, QVector<QString> recipientJids, @@ -336,6 +335,9 @@ public: const QByteArray &serializedSignedPublicPreKeySignature, const QByteArray &serializedPublicPreKey, uint32_t publicPreKeyId); + + bool deserializeIdentityKeyPair(ratchet_identity_key_pair **identityKeyPair) const; + bool deserializePrivateIdentityKey(ec_private_key **privateIdentityKey, const QByteArray &serializedPrivateIdentityKey) const; bool deserializePublicIdentityKey(ec_public_key **publicIdentityKey, const QByteArray &serializedPublicIdentityKey) const; bool deserializeSignedPublicPreKey(ec_public_key **signedPublicPreKey, const QByteArray &serializedSignedPublicPreKey) const; bool deserializePublicPreKey(ec_public_key **publicPreKey, const QByteArray &serializedPublicPreKey) const; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e599ec47..ce2ca155 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,9 +9,9 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Test) macro(add_simple_test TEST_NAME) add_executable(tst_${TEST_NAME} ${TEST_NAME}/tst_${TEST_NAME}.cpp ${ARGN}) add_test(tst_${TEST_NAME} tst_${TEST_NAME}) - target_link_libraries(tst_${TEST_NAME} Qt${QT_VERSION_MAJOR}::Test qxmpp) + target_link_libraries(tst_${TEST_NAME} Qt${QT_VERSION_MAJOR}::Test ${QXMPP_TARGET}) if(BUILD_OMEMO) - target_link_libraries(tst_${TEST_NAME} QXmppOmemo) + target_link_libraries(tst_${TEST_NAME} ${QXMPPOMEMO_TARGET}) endif() endmacro() diff --git a/tests/qxmpphttpuploadmanager/CMakeLists.txt b/tests/qxmpphttpuploadmanager/CMakeLists.txt index ceb88b1d..3858a7e7 100644 --- a/tests/qxmpphttpuploadmanager/CMakeLists.txt +++ b/tests/qxmpphttpuploadmanager/CMakeLists.txt @@ -5,4 +5,4 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_executable(tst_qxmpphttpuploadmanager tst_qxmpphttpuploadmanager.cpp tst_qxmpphttpuploadmanager.qrc ../TestClient.h) add_test(tst_qxmpphttpuploadmanager tst_qxmpphttpuploadmanager) -target_link_libraries(tst_qxmpphttpuploadmanager Qt${QT_VERSION_MAJOR}::Test qxmpp) +target_link_libraries(tst_qxmpphttpuploadmanager Qt${QT_VERSION_MAJOR}::Test ${QXMPP_TARGET}) diff --git a/tests/qxmpprostermanager/tst_qxmpprostermanager.cpp b/tests/qxmpprostermanager/tst_qxmpprostermanager.cpp index 13cd3cb7..fdeb664b 100644 --- a/tests/qxmpprostermanager/tst_qxmpprostermanager.cpp +++ b/tests/qxmpprostermanager/tst_qxmpprostermanager.cpp @@ -117,14 +117,14 @@ void tst_QXmppRosterManager::testAddItem() auto *rosterManager = test.addNewExtension<QXmppRosterManager>(&test); auto future = rosterManager->addRosterItem("contact@example.org"); - test.expect("<iq id='qxmpp1' to='capulet.lit' type='set'><query xmlns='jabber:iq:roster'><item jid='contact@example.org'/></query></iq>"); - test.inject<QString>("<iq id='qxmpp1' from='capulet.lit' type='result'/>"); + test.expect("<iq id='qxmpp1' type='set'><query xmlns='jabber:iq:roster'><item jid='contact@example.org'/></query></iq>"); + test.inject<QString>("<iq id='qxmpp1' type='result'/>"); expectFutureVariant<QXmpp::Success>(future); future = rosterManager->addRosterItem("contact@example.org"); - test.expect("<iq id='qxmpp1' to='capulet.lit' type='set'><query xmlns='jabber:iq:roster'><item jid='contact@example.org'/></query></iq>"); + test.expect("<iq id='qxmpp1' type='set'><query xmlns='jabber:iq:roster'><item jid='contact@example.org'/></query></iq>"); test.inject<QString>(R"( -<iq id='qxmpp1' from='capulet.lit' type='error'> +<iq id='qxmpp1' type='error'> <error type='modify'> <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>This is not allowed</text> @@ -143,14 +143,14 @@ void tst_QXmppRosterManager::testRemoveItem() auto *rosterManager = test.addNewExtension<QXmppRosterManager>(&test); auto future = rosterManager->removeRosterItem("contact@example.org"); - test.expect("<iq id='qxmpp1' to='capulet.lit' type='set'><query xmlns='jabber:iq:roster'><item jid='contact@example.org' subscription='remove'/></query></iq>"); - test.inject<QString>("<iq id='qxmpp1' from='capulet.lit' type='result'/>"); + test.expect("<iq id='qxmpp1' type='set'><query xmlns='jabber:iq:roster'><item jid='contact@example.org' subscription='remove'/></query></iq>"); + test.inject<QString>("<iq id='qxmpp1' type='result'/>"); expectFutureVariant<QXmpp::Success>(future); future = rosterManager->removeRosterItem("contact@example.org"); - test.expect("<iq id='qxmpp1' to='capulet.lit' type='set'><query xmlns='jabber:iq:roster'><item jid='contact@example.org' subscription='remove'/></query></iq>"); + test.expect("<iq id='qxmpp1' type='set'><query xmlns='jabber:iq:roster'><item jid='contact@example.org' subscription='remove'/></query></iq>"); test.inject<QString>(R"( -<iq id='qxmpp1' from='capulet.lit' type='error'> +<iq id='qxmpp1' type='error'> <error type='cancel'> <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Not found</text> diff --git a/tests/qxmpptransfermanager/CMakeLists.txt b/tests/qxmpptransfermanager/CMakeLists.txt index 2c9f4000..bb512489 100644 --- a/tests/qxmpptransfermanager/CMakeLists.txt +++ b/tests/qxmpptransfermanager/CMakeLists.txt @@ -5,4 +5,4 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_executable(tst_qxmpptransfermanager tst_qxmpptransfermanager.cpp tst_qxmpptransfermanager.qrc) add_test(tst_qxmpptransfermanager tst_qxmpptransfermanager) -target_link_libraries(tst_qxmpptransfermanager Qt${QT_VERSION_MAJOR}::Test qxmpp) +target_link_libraries(tst_qxmpptransfermanager Qt${QT_VERSION_MAJOR}::Test ${QXMPP_TARGET}) diff --git a/tests/qxmpputils/CMakeLists.txt b/tests/qxmpputils/CMakeLists.txt index 9ea884c6..c2337834 100644 --- a/tests/qxmpputils/CMakeLists.txt +++ b/tests/qxmpputils/CMakeLists.txt @@ -5,4 +5,4 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_executable(tst_qxmpputils tst_qxmpputils.cpp tst_qxmpputils.qrc) add_test(tst_qxmpputils tst_qxmpputils) -target_link_libraries(tst_qxmpputils Qt${QT_VERSION_MAJOR}::Test qxmpp) +target_link_libraries(tst_qxmpputils Qt${QT_VERSION_MAJOR}::Test ${QXMPP_TARGET}) |
