File indexing completed on 2024-09-15 04:36:24

0001 /*
0002     SPDX-FileCopyrightText: 2011 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "dbus_p.h"
0008 #include "instance_p.h"
0009 
0010 #include <QList>
0011 #include <QString>
0012 #include <QStringList>
0013 #include <QStringView>
0014 
0015 #include <array>
0016 
0017 using namespace Akonadi;
0018 
0019 #define AKONADI_DBUS_SERVER_SERVICE u"org.freedesktop.Akonadi"
0020 #define AKONADI_DBUS_CONTROL_SERVICE u"org.freedesktop.Akonadi.Control"
0021 #define AKONADI_DBUS_CONTROL_SERVICE_LOCK u"org.freedesktop.Akonadi.Control.lock"
0022 #define AKONADI_DBUS_AGENTSERVER_SERVICE u"org.freedesktop.Akonadi.AgentServer"
0023 #define AKONADI_DBUS_STORAGEJANITOR_SERVICE u"org.freedesktop.Akonadi.Janitor"
0024 #define AKONADI_DBUS_SERVER_SERVICE_UPGRADING u"org.freedesktop.Akonadi.upgrading"
0025 
0026 static QString makeServiceName(QStringView base)
0027 {
0028     if (!Instance::hasIdentifier()) {
0029         return base.toString();
0030     }
0031     return base + QLatin1Char('.') + Instance::identifier();
0032 }
0033 
0034 QString DBus::serviceName(DBus::ServiceType serviceType)
0035 {
0036     switch (serviceType) {
0037     case Server:
0038         return makeServiceName(AKONADI_DBUS_SERVER_SERVICE);
0039     case Control:
0040         return makeServiceName(AKONADI_DBUS_CONTROL_SERVICE);
0041     case ControlLock:
0042         return makeServiceName(AKONADI_DBUS_CONTROL_SERVICE_LOCK);
0043     case AgentServer:
0044         return makeServiceName(AKONADI_DBUS_AGENTSERVER_SERVICE);
0045     case StorageJanitor:
0046         return makeServiceName(AKONADI_DBUS_STORAGEJANITOR_SERVICE);
0047     case UpgradeIndicator:
0048         return makeServiceName(AKONADI_DBUS_SERVER_SERVICE_UPGRADING);
0049     }
0050     Q_ASSERT(!"WTF?");
0051     return QString();
0052 }
0053 
0054 std::optional<DBus::AgentService> DBus::parseAgentServiceName(const QString &serviceName)
0055 {
0056     if (!serviceName.startsWith(AKONADI_DBUS_SERVER_SERVICE ".")) {
0057         return std::nullopt;
0058     }
0059     const auto parts = QStringView(serviceName).mid(QStringView(AKONADI_DBUS_SERVER_SERVICE ".").length()).split(QLatin1Char('.'));
0060     if ((parts.size() == 2 && !Akonadi::Instance::hasIdentifier())
0061         || (parts.size() == 3 && Akonadi::Instance::hasIdentifier() && Akonadi::Instance::identifier() == parts.at(2))) {
0062         // switch on parts.at( 0 )
0063         if (parts.at(0) == QLatin1StringView("Agent")) {
0064             return AgentService{parts.at(1).toString(), DBus::Agent};
0065         } else if (parts.at(0) == QLatin1StringView("Resource")) {
0066             return AgentService{parts.at(1).toString(), DBus::Resource};
0067         } else if (parts.at(0) == QLatin1StringView("Preprocessor")) {
0068             return AgentService{parts.at(1).toString(), DBus::Preprocessor};
0069         } else {
0070             return std::nullopt;
0071         }
0072     }
0073 
0074     return std::nullopt;
0075 }
0076 
0077 QString DBus::agentServiceName(const QString &agentIdentifier, DBus::AgentType agentType)
0078 {
0079     Q_ASSERT(!agentIdentifier.isEmpty());
0080     Q_ASSERT(agentType != Unknown);
0081     QString serviceName = QStringLiteral(AKONADI_DBUS_SERVER_SERVICE ".");
0082     switch (agentType) {
0083     case Agent:
0084         serviceName += QLatin1StringView("Agent.");
0085         break;
0086     case Resource:
0087         serviceName += QLatin1StringView("Resource.");
0088         break;
0089     case Preprocessor:
0090         serviceName += QLatin1StringView("Preprocessor.");
0091         break;
0092     default:
0093         Q_ASSERT(!"WTF?");
0094     }
0095     serviceName += agentIdentifier;
0096     if (Akonadi::Instance::hasIdentifier()) {
0097         serviceName += QLatin1Char('.') % Akonadi::Instance::identifier();
0098     }
0099     return serviceName;
0100 }
0101 
0102 std::optional<QString> DBus::parseInstanceIdentifier(const QString &serviceName)
0103 {
0104     constexpr std::array<QStringView, 5> services = {QStringView{AKONADI_DBUS_STORAGEJANITOR_SERVICE},
0105                                                      QStringView{AKONADI_DBUS_SERVER_SERVICE_UPGRADING},
0106                                                      QStringView{AKONADI_DBUS_AGENTSERVER_SERVICE},
0107                                                      QStringView{AKONADI_DBUS_CONTROL_SERVICE_LOCK},
0108                                                      QStringView{AKONADI_DBUS_CONTROL_SERVICE}};
0109     for (const auto &service : services) {
0110         if (serviceName.startsWith(service)) {
0111             if (serviceName != service) {
0112                 return serviceName.mid(service.length() + 1); // +1 for the separator "."
0113             }
0114             return std::nullopt;
0115         }
0116     }
0117 
0118     if (serviceName.startsWith(QStringView{AKONADI_DBUS_SERVER_SERVICE})) {
0119         const auto split = QStringView(serviceName).split(QLatin1Char('.'));
0120         if (split.size() <= 3) {
0121             return std::nullopt;
0122         }
0123 
0124         // [0]org.[1]freedesktop.[2]Akonadi.[3]type.[4]identifier.[5]instance
0125         if (split[3] == QStringView{u"Agent"} || split[3] == QStringView{u"Resource"} || split[3] == QStringView{u"Preprocessor"}) {
0126             if (split.size() == 6) {
0127                 return split[5].toString();
0128             } else {
0129                 return std::nullopt;
0130             }
0131         } else {
0132             return split[3].toString();
0133         }
0134     }
0135 
0136     return std::nullopt;
0137 }