Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kdeconnect-kde for openSUSE:Factory 
checked in at 2023-05-22 13:14:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kdeconnect-kde (Old)
 and      /work/SRC/openSUSE:Factory/.kdeconnect-kde.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kdeconnect-kde"

Mon May 22 13:14:08 2023 rev:64 rq:1088126 version:23.04.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/kdeconnect-kde/kdeconnect-kde.changes    
2023-05-12 20:33:35.708796820 +0200
+++ /work/SRC/openSUSE:Factory/.kdeconnect-kde.new.1533/kdeconnect-kde.changes  
2023-05-22 13:14:11.902769298 +0200
@@ -1,0 +2,7 @@
+Sun May 21 08:58:13 UTC 2023 - Fusion Future <[email protected]>
+
+- Add patch to avoid incorrect notification IDs from the notification
+  plugin (kde#447385):
+  * Use-org-freedesktop-DBus-Monitoring-to-monitor-notifications.patch
+
+-------------------------------------------------------------------

New:
----
  Use-org-freedesktop-DBus-Monitoring-to-monitor-notifications.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kdeconnect-kde.spec ++++++
--- /var/tmp/diff_new_pack.C5Fblb/_old  2023-05-22 13:14:12.442771993 +0200
+++ /var/tmp/diff_new_pack.C5Fblb/_new  2023-05-22 13:14:12.446772012 +0200
@@ -29,6 +29,8 @@
 Source2:        applications.keyring
 %endif
 Source100:      kdeconnect-kde.SuSEfirewall
+#PATCH-FIX-UPSTREAM kde#447385
+Patch0:         
Use-org-freedesktop-DBus-Monitoring-to-monitor-notifications.patch
 BuildRequires:  cmake >= 3.0
 BuildRequires:  extra-cmake-modules
 BuildRequires:  kf5-filesystem
@@ -61,6 +63,7 @@
 BuildRequires:  cmake(Qt5X11Extras)
 BuildRequires:  cmake(Qt5WaylandClient)
 BuildRequires:  pkgconfig(dbus-1)
+BuildRequires:  pkgconfig(gio-2.0)
 BuildRequires:  pkgconfig(libfakekey)
 BuildRequires:  pkgconfig(x11)
 BuildRequires:  pkgconfig(xkbcommon)

++++++ Use-org-freedesktop-DBus-Monitoring-to-monitor-notifications.patch ++++++
>From 4523ba588276bc5d2bc7f0e11cf39743efeca263 Mon Sep 17 00:00:00 2001
From: Fushan Wen <[email protected]>
Date: Mon, 13 Mar 2023 02:20:12 +0000
Subject: [PATCH] Use `org.freedesktop.DBus.Monitoring` to monitor
 notifications

Plasma notification widget also uses the interface, and sometimes
notification ids can become out of sync between the two DBus adaptors.

BUG: 447385
FIXED-IN: 23.08
---
 CMakeLists.txt                                |   1 +
 plugins/sendnotifications/CMakeLists.txt      |   1 +
 .../notificationslistener.cpp                 | 238 +++++++++++++-----
 .../sendnotifications/notificationslistener.h |  17 +-
 4 files changed, 181 insertions(+), 76 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 898130a9d..ed3c4f13b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,6 +85,7 @@ else()
         find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS WaylandClient)
         find_package(WaylandProtocols REQUIRED)
         pkg_check_modules(XkbCommon IMPORTED_TARGET xkbcommon)
+        pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
     endif()
 
     find_package(KF5PeopleVCard)
diff --git a/plugins/sendnotifications/CMakeLists.txt 
b/plugins/sendnotifications/CMakeLists.txt
index 90bcde7af..f994f7f2e 100644
--- a/plugins/sendnotifications/CMakeLists.txt
+++ b/plugins/sendnotifications/CMakeLists.txt
@@ -30,6 +30,7 @@ target_link_libraries(kdeconnect_sendnotifications
     Qt::Gui
     KF5::IconThemes
     KF5::ConfigCore
+    PkgConfig::GIO
 )
 
 #######################################
diff --git a/plugins/sendnotifications/notificationslistener.cpp 
b/plugins/sendnotifications/notificationslistener.cpp
index f4982b997..8b5894d3d 100644
--- a/plugins/sendnotifications/notificationslistener.cpp
+++ b/plugins/sendnotifications/notificationslistener.cpp
@@ -5,13 +5,17 @@
  */
 #include "notificationslistener.h"
 
+#include <unordered_map>
+
 #include <KConfig>
 #include <KConfigGroup>
 #include <QDBusArgument>
 #include <QDBusInterface>
 #include <QImage>
+#include <QScopeGuard>
 #include <QStandardPaths>
 #include <QtDebug>
+
 #include <kiconloader.h>
 #include <kicontheme.h>
 
@@ -28,20 +32,26 @@
 #include "qtcompat_p.h"
 
 NotificationsListener::NotificationsListener(KdeConnectPlugin *aPlugin)
-    : QDBusAbstractAdaptor(aPlugin)
+    : QObject(aPlugin)
     , m_plugin(aPlugin)
 {
     
qRegisterMetaTypeStreamOperators<NotifyingApplication>("NotifyingApplication");
 
-    bool ret = 
QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/freedesktop/Notifications"),
 this, QDBusConnection::ExportScriptableContents);
-    if (!ret)
-        qCWarning(KDECONNECT_PLUGIN_SENDNOTIFICATION) << "Error registering 
notifications listener for device" << m_plugin->device()->name() << ":"
-                                                      << 
QDBusConnection::sessionBus().lastError();
-    else
-        qCDebug(KDECONNECT_PLUGIN_SENDNOTIFICATION) << "Registered 
notifications listener for device" << m_plugin->device()->name();
+    GError *error = nullptr;
+    m_gdbusConnection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error);
+    g_assert_no_error(error);
+    m_gdbusFilterId = g_dbus_connection_add_filter(m_gdbusConnection, 
NotificationsListener::onMessageFiltered, this, nullptr);
+
+    g_autoptr(GDBusMessage) msg =
+        g_dbus_message_new_method_call("org.freedesktop.DBus", 
"/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
+
+    GVariantBuilder *arrayBuilder = 
g_variant_builder_new(G_VARIANT_TYPE("as"));
+    g_variant_builder_add(arrayBuilder, "s", 
"interface='org.freedesktop.Notifications'");
+    g_variant_builder_add(arrayBuilder, "s", "member='Notify'");
 
-    QDBusInterface iface(QStringLiteral("org.freedesktop.DBus"), 
QStringLiteral("/org/freedesktop/DBus"), 
QStringLiteral("org.freedesktop.DBus"));
-    iface.call(QStringLiteral("AddMatch"), 
QStringLiteral("interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'"));
+    g_dbus_message_set_body(msg, g_variant_new("(asu)", arrayBuilder, 0u));
+    g_dbus_connection_send_message(m_gdbusConnection, msg, 
GDBusSendMessageFlags::G_DBUS_SEND_MESSAGE_FLAGS_NONE, nullptr, &error);
+    g_assert_no_error(error);
 
     setTranslatedAppName();
     loadApplications();
@@ -52,10 +62,8 @@ 
NotificationsListener::NotificationsListener(KdeConnectPlugin *aPlugin)
 NotificationsListener::~NotificationsListener()
 {
     qCDebug(KDECONNECT_PLUGIN_SENDNOTIFICATION) << "Destroying 
NotificationsListener";
-    QDBusInterface iface(QStringLiteral("org.freedesktop.DBus"), 
QStringLiteral("/org/freedesktop/DBus"), 
QStringLiteral("org.freedesktop.DBus"));
-    QDBusMessage res = iface.call(QStringLiteral("RemoveMatch"),
-                                  
QStringLiteral("interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'"));
-    
QDBusConnection::sessionBus().unregisterObject(QStringLiteral("/org/freedesktop/Notifications"));
+    g_dbus_connection_remove_filter(m_gdbusConnection, m_gdbusFilterId);
+    g_object_unref(m_gdbusConnection);
 }
 
 void NotificationsListener::setTranslatedAppName()
@@ -86,7 +94,7 @@ void NotificationsListener::loadApplications()
     // qCDebug(KDECONNECT_PLUGIN_SENDNOTIFICATION) << "Loaded" << 
applications.size() << " applications";
 }
 
-bool NotificationsListener::parseImageDataArgument(const QVariant &argument,
+bool NotificationsListener::parseImageDataArgument(GVariant *argument,
                                                    int &width,
                                                    int &height,
                                                    int &rowStride,
@@ -95,16 +103,58 @@ bool NotificationsListener::parseImageDataArgument(const 
QVariant &argument,
                                                    bool &hasAlpha,
                                                    QByteArray &imageData) const
 {
-    if (!argument.canConvert<QDBusArgument>())
+    if (g_variant_n_children(argument) != 7) {
         return false;
-    const QDBusArgument dbusArg = argument.value<QDBusArgument>();
-    dbusArg.beginStructure();
-    dbusArg >> width >> height >> rowStride >> hasAlpha >> bitsPerSample >> 
channels >> imageData;
-    dbusArg.endStructure();
+    }
+
+    g_autoptr(GVariant) variant;
+
+    variant = g_variant_get_child_value(argument, 0);
+    if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT32)) {
+        return false;
+    }
+    width = g_variant_get_int32(variant);
+
+    variant = g_variant_get_child_value(argument, 1);
+    if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT32)) {
+        return false;
+    }
+    height = g_variant_get_int32(variant);
+
+    variant = g_variant_get_child_value(argument, 2);
+    if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT32)) {
+        return false;
+    }
+    rowStride = g_variant_get_int32(variant);
+
+    variant = g_variant_get_child_value(argument, 3);
+    if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) {
+        return false;
+    }
+    hasAlpha = g_variant_get_boolean(variant);
+
+    variant = g_variant_get_child_value(argument, 4);
+    if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT32)) {
+        return false;
+    }
+    bitsPerSample = g_variant_get_int32(variant);
+
+    variant = g_variant_get_child_value(argument, 5);
+    if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT32)) {
+        return false;
+    }
+    channels = g_variant_get_int32(variant);
+
+    variant = g_variant_get_child_value(argument, 6);
+    if (g_variant_is_of_type(variant, G_VARIANT_TYPE_ARRAY)) {
+        return false;
+    }
+    imageData = g_variant_get_bytestring(variant);
+
     return true;
 }
 
-QSharedPointer<QIODevice> NotificationsListener::iconForImageData(const 
QVariant &argument) const
+QSharedPointer<QIODevice> NotificationsListener::iconForImageData(GVariant 
*argument) const
 {
     int width, height, rowStride, bitsPerSample, channels;
     bool hasAlpha;
@@ -133,7 +183,7 @@ QSharedPointer<QIODevice> 
NotificationsListener::iconForImageData(const QVariant
     return buffer;
 }
 
-QSharedPointer<QIODevice> NotificationsListener::iconForIconName(const QString 
&iconName) const
+QSharedPointer<QIODevice> NotificationsListener::iconForIconName(const QString 
&iconName)
 {
     int size = KIconLoader::SizeEnormous; // use big size to allow for good
                                           // quality on high-DPI mobile devices
@@ -154,65 +204,110 @@ QSharedPointer<QIODevice> 
NotificationsListener::iconForIconName(const QString &
     return QSharedPointer<QIODevice>();
 }
 
-uint NotificationsListener::Notify(const QString &appName,
-                                   uint replacesId,
-                                   const QString &appIcon,
-                                   const QString &summary,
-                                   const QString &body,
-                                   const QStringList &actions,
-                                   const QVariantMap &hints,
-                                   int timeout)
+GDBusMessage *NotificationsListener::onMessageFiltered(GDBusConnection *, 
GDBusMessage *msg, int, void *parent)
 {
-    static int id = 0;
-    Q_UNUSED(actions);
+    static unsigned id = 0;
+    if (!msg) {
+        return msg;
+    }
+
+    const gchar *interface = g_dbus_message_get_interface(msg);
+    if (!interface || strcmp(interface, "org.freedesktop.Notifications")) {
+        // The first message will be from org.freedesktop.DBus.Monitoring
+        return msg;
+    }
+    const gchar *member = g_dbus_message_get_member(msg);
+    if (!member || strcmp(member, "Notify")) {
+        // Even if member is set, the monitor will still notify messages from 
other members.
+        return nullptr;
+    }
 
-    // qCDebug(KDECONNECT_PLUGIN_SENDNOTIFICATION) << "Got notification 
appName=" << appName << "replacesId=" << replacesId << "appIcon=" << appIcon <<
-    // "summary=" << summary << "body=" << body << "actions=" << actions << 
"hints=" << hints << "timeout=" << timeout;
+    g_autoptr(GVariant) bodyVariant = g_dbus_message_get_body(msg);
+    Q_ASSERT(bodyVariant);
 
+    // Data order and types: 
https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html
+    g_autoptr(GVariant) variant = g_variant_get_child_value(bodyVariant, 0);
+    const QString appName = QString::fromUtf8(g_variant_get_string(variant, 
nullptr));
     // skip our own notifications
-    if (appName == m_translatedAppName)
-        return 0;
+    auto listener = static_cast<NotificationsListener *>(parent);
+
+    if (appName == listener->m_translatedAppName) {
+        return nullptr;
+    }
+
+    variant = g_variant_get_child_value(bodyVariant, 2);
+    const QString appIcon = QString::fromUtf8(g_variant_get_string(variant, 
nullptr));
 
     NotifyingApplication app;
-    if (!m_applications.contains(appName)) {
+    if (!listener->m_applications.contains(appName)) {
         // new application -> add to config
         app.name = appName;
         app.icon = appIcon;
         app.active = true;
         app.blacklistExpression = QRegularExpression();
-        m_applications.insert(app.name, app);
+        listener->m_applications.insert(app.name, app);
         // update config:
         QVariantList list;
-        for (const auto &a : qAsConst(m_applications))
+        for (const auto &a : std::as_const(listener->m_applications))
             list << QVariant::fromValue<NotifyingApplication>(a);
-        m_plugin->config()->setList(QStringLiteral("applications"), list);
+        listener->m_plugin->config()->setList(QStringLiteral("applications"), 
list);
         // qCDebug(KDECONNECT_PLUGIN_SENDNOTIFICATION) << "Added new 
application to config:" << app;
     } else {
-        app = m_applications.value(appName);
+        app = listener->m_applications.value(appName);
+    }
+
+    if (!app.active) {
+        return nullptr;
     }
 
-    if (!app.active)
-        return 0;
+    variant = g_variant_get_child_value(bodyVariant, 7);
+    const auto timeout = g_variant_get_int32(variant);
+    if (timeout > 0 && 
listener->m_plugin->config()->getBool(QStringLiteral("generalPersistent"), 
false)) {
+        return nullptr;
+    }
+
+    variant = g_variant_get_child_value(bodyVariant, 6);
+    std::unordered_map<QString, GVariant *> hints;
+    GVariantIter *iter;
+    const gchar *key;
+    GVariant *value = nullptr;
+    g_variant_get(variant, "a{sv}", &iter);
+    while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
+        hints.emplace(QString::fromUtf8(key), value);
+    }
+    g_variant_iter_free(iter);
 
-    if (timeout > 0 && 
m_plugin->config()->getBool(QStringLiteral("generalPersistent"), false))
-        return 0;
+    QScopeGuard cleanupHints([&hints] {
+        for (auto &[_, hint] : hints) {
+            g_variant_unref(hint);
+        }
+    });
 
     int urgency = -1;
-    if (hints.contains(QStringLiteral("urgency"))) {
-        bool ok;
-        urgency = hints[QStringLiteral("urgency")].toInt(&ok);
-        if (!ok)
-            urgency = -1;
+    if (auto it = hints.find(QStringLiteral("urgency")); it != hints.end()) {
+        if (g_variant_is_of_type(it->second, G_VARIANT_TYPE_BYTE)) {
+            urgency = g_variant_get_byte(it->second);
+        }
     }
-    if (urgency > -1 && urgency < 
m_plugin->config()->getInt(QStringLiteral("generalUrgency"), 0))
-        return 0;
+    if (urgency > -1 && urgency < 
listener->m_plugin->config()->getInt(QStringLiteral("generalUrgency"), 0))
+        return nullptr;
+
+    variant = g_variant_get_child_value(bodyVariant, 3);
+    QString ticker = QString::fromUtf8(g_variant_get_string(variant, nullptr));
 
-    QString ticker = summary;
-    if (!body.isEmpty() && 
m_plugin->config()->getBool(QStringLiteral("generalIncludeBody"), true))
+    variant = g_variant_get_child_value(bodyVariant, 4);
+    const QString body = QString::fromUtf8(g_variant_get_string(variant, 
nullptr));
+
+    if (!body.isEmpty() && 
listener->m_plugin->config()->getBool(QStringLiteral("generalIncludeBody"), 
true)) {
         ticker += QStringLiteral(": ") + body;
+    }
+
+    if (app.blacklistExpression.isValid() && 
!app.blacklistExpression.pattern().isEmpty() && 
app.blacklistExpression.match(ticker).hasMatch()) {
+        return nullptr;
+    }
 
-    if (app.blacklistExpression.isValid() && 
!app.blacklistExpression.pattern().isEmpty() && 
app.blacklistExpression.match(ticker).hasMatch())
-        return 0;
+    variant = g_variant_get_child_value(bodyVariant, 1);
+    const unsigned replacesId = g_variant_get_uint32(variant);
 
     // qCDebug(KDECONNECT_PLUGIN_SENDNOTIFICATION) << "Sending notification 
from" << appName << ":" <<ticker << "; appIcon=" << appIcon;
     NetworkPacket np(PACKET_TYPE_NOTIFICATION,
@@ -224,28 +319,33 @@ uint NotificationsListener::Notify(const QString &appName,
                                                                        // 
clearability is pointless
 
     // sync any icon data?
-    if (m_plugin->config()->getBool(QStringLiteral("generalSynchronizeIcons"), 
true)) {
+    if 
(listener->m_plugin->config()->getBool(QStringLiteral("generalSynchronizeIcons"),
 true)) {
         QSharedPointer<QIODevice> iconSource;
         // try different image sources according to priorities in 
notifications-
         // spec version 1.2:
-        if (hints.contains(QStringLiteral("image-data")))
-            iconSource = iconForImageData(hints[QStringLiteral("image-data")]);
-        else if (hints.contains(QStringLiteral("image_data"))) // 1.1 backward 
compatibility
-            iconSource = iconForImageData(hints[QStringLiteral("image_data")]);
-        else if (hints.contains(QStringLiteral("image-path")))
-            iconSource = 
iconForIconName(hints[QStringLiteral("image-path")].toString());
-        else if (hints.contains(QStringLiteral("image_path"))) // 1.1 backward 
compatibility
-            iconSource = 
iconForIconName(hints[QStringLiteral("image_path")].toString());
-        else if (!appIcon.isEmpty())
+        if (auto it = hints.find(QStringLiteral("image-data")); it != 
hints.end()) {
+            iconSource = listener->iconForImageData(it->second);
+        } else if (auto it = hints.find(QStringLiteral("image_data")); it != 
hints.end()) { // 1.1 backward compatibility
+            iconSource = listener->iconForImageData(it->second);
+        } else if (auto it = hints.find(QStringLiteral("image-path")); it != 
hints.end()) {
+            iconSource = 
iconForIconName(QString::fromUtf8(g_variant_get_string(it->second, nullptr)));
+        } else if (auto it = hints.find(QStringLiteral("image_path")); it != 
hints.end()) { // 1.1 backward compatibility
+            iconSource = 
iconForIconName(QString::fromUtf8(g_variant_get_string(it->second, nullptr)));
+        } else if (!appIcon.isEmpty()) {
             iconSource = iconForIconName(appIcon);
-        else if (hints.contains(QStringLiteral("icon_data"))) // < 1.1 
backward compatibility
-            iconSource = iconForImageData(hints[QStringLiteral("icon_data")]);
+        } else if (auto it = hints.find(QStringLiteral("icon_data")); it != 
hints.end()) { // < 1.1 backward compatibility
+            iconSource = listener->iconForImageData(it->second);
+        }
 
         if (iconSource)
             np.setPayload(iconSource, iconSource->size());
     }
 
-    m_plugin->sendPacket(np);
+    listener->m_plugin->sendPacket(np);
+
+    qCDebug(KDECONNECT_PLUGIN_SENDNOTIFICATION) << "Got notification appName=" 
<< appName << "replacesId=" << replacesId << "appIcon=" << appIcon
+                                                << "summary=" << ticker << 
"body=" << body << "hints=" << hints.size() << "urgency=" << urgency
+                                                << "timeout=" << timeout;
 
-    return (replacesId > 0 ? replacesId : id);
+    return nullptr;
 }
diff --git a/plugins/sendnotifications/notificationslistener.h 
b/plugins/sendnotifications/notificationslistener.h
index 38fcd7688..f1d55a453 100644
--- a/plugins/sendnotifications/notificationslistener.h
+++ b/plugins/sendnotifications/notificationslistener.h
@@ -13,14 +13,15 @@
 #include <QFile>
 #include <core/device.h>
 
+#include <gio/gio.h>
+
 class KdeConnectPlugin;
 class Notification;
 struct NotifyingApplication;
 
-class NotificationsListener : public QDBusAbstractAdaptor
+class NotificationsListener : public QObject
 {
     Q_OBJECT
-    Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Notifications")
 
 public:
     explicit NotificationsListener(KdeConnectPlugin *aPlugin);
@@ -32,7 +33,7 @@ protected:
 
     // virtual helper function to make testing possible (QDBusArgument can not
     // be injected without making a DBUS-call):
-    virtual bool parseImageDataArgument(const QVariant &argument,
+    virtual bool parseImageDataArgument(GVariant *argument,
                                         int &width,
                                         int &height,
                                         int &rowStride,
@@ -40,11 +41,10 @@ protected:
                                         int &channels,
                                         bool &hasAlpha,
                                         QByteArray &imageData) const;
-    QSharedPointer<QIODevice> iconForImageData(const QVariant &argument) const;
-    QSharedPointer<QIODevice> iconForIconName(const QString &iconName) const;
+    QSharedPointer<QIODevice> iconForImageData(GVariant *argument) const;
+    static QSharedPointer<QIODevice> iconForIconName(const QString &iconName);
 
-public Q_SLOTS:
-    Q_SCRIPTABLE uint Notify(const QString &, uint, const QString &, const 
QString &, const QString &, const QStringList &, const QVariantMap &, int);
+    static GDBusMessage *onMessageFiltered(GDBusConnection *connection, 
GDBusMessage *msg, int incoming, void *parent);
 
 private Q_SLOTS:
     void loadApplications();
@@ -52,6 +52,9 @@ private Q_SLOTS:
 private:
     void setTranslatedAppName();
     QString m_translatedAppName;
+
+    GDBusConnection *m_gdbusConnection = nullptr;
+    unsigned m_gdbusFilterId = 0;
 };
 
 #endif // NOTIFICATIONSLISTENER_H
-- 
GitLab

Reply via email to