LCOV - code coverage report
Current view: top level - src/plugin - jamipluginmanager.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 203 299 67.9 %
Date: 2024-11-15 09:04:49 Functions: 24 32 75.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "jamipluginmanager.h"
      19             : #include "pluginsutils.h"
      20             : #include "fileutils.h"
      21             : #include "archiver.h"
      22             : #include "logger.h"
      23             : #include "manager.h"
      24             : #include "jami/plugin_manager_interface.h"
      25             : #include "store_ca_crt.cpp"
      26             : 
      27             : #include <fstream>
      28             : #include <stdexcept>
      29             : #include <msgpack.hpp>
      30             : 
      31             : #define FAILURE                        -1
      32             : #define SUCCESS                         0
      33             : #define PLUGIN_ALREADY_INSTALLED        100 /* Plugin already installed with the same version */
      34             : #define PLUGIN_OLD_VERSION              200 /* Plugin already installed with a newer version */
      35             : #define SIGNATURE_VERIFICATION_FAILED   300
      36             : #define CERTIFICATE_VERIFICATION_FAILED 400
      37             : #define INVALID_PLUGIN                  500
      38             : 
      39             : 
      40             : #ifdef WIN32
      41             : #define LIB_TYPE   ".dll"
      42             : #define LIB_PREFIX ""
      43             : #else
      44             : #ifdef __APPLE__
      45             : #define LIB_TYPE   ".dylib"
      46             : #define LIB_PREFIX "lib"
      47             : #else
      48             : #define LIB_TYPE   ".so"
      49             : #define LIB_PREFIX "lib"
      50             : #endif
      51             : #endif
      52             : 
      53             : namespace jami {
      54             : 
      55          33 : JamiPluginManager::JamiPluginManager()
      56          33 :     : callsm_ {pm_}
      57          33 :     , chatsm_ {pm_}
      58          33 :     , webviewsm_ {pm_}
      59          66 :     , preferencesm_ {pm_}
      60             : {
      61          33 :     registerServices();
      62          33 : }
      63             : 
      64             : std::string
      65           9 : JamiPluginManager::getPluginAuthor(const std::string& rootPath, const std::string& pluginId)
      66             : {
      67           9 :     auto cert = PluginUtils::readPluginCertificate(rootPath, pluginId);
      68           9 :     if (!cert) {
      69           0 :         JAMI_ERROR("Unable to read plugin certificate");
      70           0 :         return {};
      71             :     }
      72           9 :     return cert->getIssuerName();
      73           9 : }
      74             : 
      75             : std::map<std::string, std::string>
      76          18 : JamiPluginManager::getPluginDetails(const std::string& rootPath, bool reset)
      77             : {
      78          18 :     auto detailsIt = pluginDetailsMap_.find(rootPath);
      79          18 :     if (detailsIt != pluginDetailsMap_.end()) {
      80          11 :         if (!reset)
      81           9 :             return detailsIt->second;
      82           2 :         pluginDetailsMap_.erase(detailsIt);
      83             :     }
      84             : 
      85             :     std::map<std::string, std::string> details = PluginUtils::parseManifestFile(
      86          18 :         PluginUtils::manifestPath(rootPath), rootPath);
      87           9 :     if (!details.empty()) {
      88           9 :         auto itIcon = details.find("iconPath");
      89           9 :         itIcon->second.insert(0, rootPath + DIR_SEPARATOR_CH + "data" + DIR_SEPARATOR_CH);
      90             : 
      91           9 :         auto itImage = details.find("backgroundPath");
      92           9 :         itImage->second.insert(0, rootPath + DIR_SEPARATOR_CH + "data" + DIR_SEPARATOR_CH);
      93             : 
      94           9 :         details["soPath"] = rootPath + DIR_SEPARATOR_CH + LIB_PREFIX + details["id"] + LIB_TYPE;
      95           9 :         details["author"] = getPluginAuthor(rootPath, details["id"]);
      96           9 :         detailsIt = pluginDetailsMap_.emplace(rootPath, std::move(details)).first;
      97           9 :         return detailsIt->second;
      98             :     }
      99           0 :     return {};
     100           9 : }
     101             : 
     102             : std::vector<std::string>
     103           2 : JamiPluginManager::getInstalledPlugins()
     104             : {
     105             :     // Gets all plugins in standard path
     106           2 :     auto pluginsPath = fileutils::get_data_dir() / "plugins";
     107           2 :     std::vector<std::string> pluginsPaths;
     108           2 :     std::error_code ec;
     109           7 :     for (const auto& entry : std::filesystem::directory_iterator(pluginsPath, ec)) {
     110           1 :         const auto& p = entry.path();
     111           1 :         if (PluginUtils::checkPluginValidity(p))
     112           1 :             pluginsPaths.emplace_back(p.string());
     113           2 :     }
     114             : 
     115             :     // Gets plugins installed in non standard path
     116           2 :     std::vector<std::string> nonStandardInstalls = jami::Manager::instance()
     117           2 :                                                        .pluginPreferences.getInstalledPlugins();
     118           2 :     for (auto& path : nonStandardInstalls) {
     119           0 :         if (PluginUtils::checkPluginValidity(path))
     120           0 :             pluginsPaths.emplace_back(path);
     121             :     }
     122             : 
     123           4 :     return pluginsPaths;
     124           2 : }
     125             : 
     126             : bool
     127           0 : JamiPluginManager::checkPluginCertificatePublicKey(const std::string& oldJplPath, const std::string& newJplPath)
     128             : {
     129           0 :     std::map<std::string, std::string> oldDetails = PluginUtils::parseManifestFile(PluginUtils::manifestPath(oldJplPath), oldJplPath);
     130           0 :     if (
     131           0 :         oldDetails.empty() ||
     132           0 :         !std::filesystem::is_regular_file(oldJplPath + DIR_SEPARATOR_CH + oldDetails["id"] + ".crt") ||
     133           0 :         !std::filesystem::is_regular_file(newJplPath)
     134             :     )
     135           0 :         return false;
     136             :     try {
     137           0 :         auto oldCert = PluginUtils::readPluginCertificate(oldJplPath, oldDetails["id"]);
     138           0 :         auto newCert = PluginUtils::readPluginCertificateFromArchive(newJplPath);
     139           0 :         if (!oldCert || !newCert) {
     140           0 :             return false;
     141             :         }
     142           0 :         return oldCert->getPublicKey() == newCert->getPublicKey();
     143           0 :     } catch (const std::exception& e) {
     144           0 :         JAMI_ERR() << e.what();
     145           0 :         return false;
     146           0 :     }
     147             :     return true;
     148           0 : }
     149             : 
     150             : bool
     151          12 : JamiPluginManager::checkPluginCertificateValidity(dht::crypto::Certificate* cert)
     152             : {
     153          12 :     trust_.add(crypto::Certificate(store_ca_crt, sizeof(store_ca_crt)));
     154          12 :     return cert && *cert && trust_.verify(*cert);
     155             : }
     156             : 
     157             : std::map<std::string, std::string>
     158           0 : JamiPluginManager::getPlatformInfo()
     159             : {
     160           0 :     return PluginUtils::getPlatformInfo();
     161             : }
     162             : 
     163             : bool
     164          12 : JamiPluginManager::checkPluginSignatureFile(const std::string& jplPath)
     165             : {
     166             :     // check if the file exists
     167          12 :     if (!std::filesystem::is_regular_file(jplPath)){
     168           1 :         return false;
     169             :     }
     170             :     try {
     171          11 :         auto signatures = PluginUtils::readPluginSignatureFromArchive(jplPath);
     172          11 :         auto manifest = PluginUtils::readPluginManifestFromArchive(jplPath);
     173          11 :         const std::string& name = manifest["id"];
     174          11 :         auto filesPath = archiver::listFilesFromArchive(jplPath);
     175         120 :         for (const auto& file : filesPath) {
     176             :             // we skip the signatures and signatures.sig file
     177         111 :             if (file == "signatures" || file == "signatures.sig")
     178          20 :                 continue;
     179             :             // we also skip the plugin certificate
     180          91 :             if (file == name + ".crt")
     181           9 :                 continue;
     182             : 
     183          82 :             if (signatures.count(file) == 0) {
     184           2 :                 return false;
     185             :             }
     186             :         }
     187          15 :     } catch (const std::exception& e) {
     188           0 :         return false;
     189           0 :     }
     190           9 :     return true;
     191             : }
     192             : 
     193             : bool
     194          11 : JamiPluginManager::checkPluginSignatureValidity(const std::string& jplPath, dht::crypto::Certificate* cert)
     195             : {
     196          11 :     if (!std::filesystem::is_regular_file(jplPath))
     197           0 :         return false;
     198             :     try{
     199          11 :         const auto& pk = cert->getPublicKey();
     200          20 :         auto signaturesData = archiver::readFileFromArchive(jplPath, "signatures");
     201          10 :         auto signatureFile = PluginUtils::readSignatureFileFromArchive(jplPath);
     202          10 :         if (!pk.checkSignature(signaturesData, signatureFile))
     203           1 :             return false;
     204           9 :         auto signatures = PluginUtils::readPluginSignatureFromArchive(jplPath);
     205          81 :         for (const auto& signature : signatures) {
     206          72 :             auto file = archiver::readFileFromArchive(jplPath, signature.first);
     207          72 :             if (!pk.checkSignature(file, signature.second)){
     208           0 :                 JAMI_ERROR("{} not correctly signed", signature.first);
     209           0 :                 return false;
     210             :             }
     211          72 :         }
     212          12 :     } catch (const std::exception& e) {
     213           1 :         return false;
     214           1 :     }
     215             : 
     216           9 :     return true;
     217             : }
     218             : 
     219             : bool
     220           9 : JamiPluginManager::checkPluginSignature(const std::string& jplPath, dht::crypto::Certificate* cert)
     221             : {
     222           9 :     if (!std::filesystem::is_regular_file(jplPath) || !cert || !*cert)
     223           1 :         return false;
     224             :     try {
     225          16 :         return  checkPluginSignatureValidity(jplPath, cert) &&
     226          16 :                 checkPluginSignatureFile(jplPath);
     227           0 :     } catch (const std::exception& e) {
     228           0 :         return false;
     229           0 :     }
     230             : }
     231             : 
     232             : std::unique_ptr<dht::crypto::Certificate>
     233          13 : JamiPluginManager::checkPluginCertificate(const std::string& jplPath, bool force)
     234             : {
     235          13 :     if (!std::filesystem::is_regular_file(jplPath))
     236           1 :         return {};
     237             :     try {
     238          12 :         auto cert = PluginUtils::readPluginCertificateFromArchive(jplPath);
     239          12 :         if(checkPluginCertificateValidity(cert.get()) || force){
     240          10 :             return cert;
     241             :         }
     242           2 :         return {};
     243          12 :     } catch (const std::exception& e) {
     244           0 :         return {};
     245           0 :     }
     246             : }
     247             : 
     248             : int
     249           7 : JamiPluginManager::installPlugin(const std::string& jplPath, bool force)
     250             : {
     251           7 :     int r {SUCCESS};
     252           7 :     if (std::filesystem::is_regular_file(jplPath)) {
     253             :         try {
     254           7 :             auto manifestMap = PluginUtils::readPluginManifestFromArchive(jplPath);
     255           7 :             const std::string& name = manifestMap["id"];
     256           7 :             if (name.empty())
     257           0 :                 return INVALID_PLUGIN;
     258           7 :             auto cert = checkPluginCertificate(jplPath, force);
     259           7 :             if (!cert)
     260           0 :                 return CERTIFICATE_VERIFICATION_FAILED;
     261           7 :             if(!checkPluginSignature(jplPath, cert.get()))
     262           0 :                 return SIGNATURE_VERIFICATION_FAILED;
     263           7 :             const std::string& version = manifestMap["version"];
     264          14 :             auto destinationDir = (fileutils::get_data_dir() / "plugins" / name).string();
     265             :             // Find if there is an existing version of this plugin
     266             :             const auto alreadyInstalledManifestMap = PluginUtils::parseManifestFile(
     267          14 :                 PluginUtils::manifestPath(destinationDir), destinationDir);
     268             : 
     269           7 :             if (!alreadyInstalledManifestMap.empty()) {
     270           2 :                 if (force) {
     271           2 :                     r = uninstallPlugin(destinationDir);
     272           2 :                     if (r == SUCCESS) {
     273           2 :                         archiver::uncompressArchive(jplPath,
     274             :                                                     destinationDir,
     275             :                                                     PluginUtils::uncompressJplFunction);
     276             :                     }
     277             :                 } else {
     278           0 :                     std::string installedVersion = alreadyInstalledManifestMap.at("version");
     279           0 :                     if (version > installedVersion) {
     280           0 :                         if(!checkPluginCertificatePublicKey(destinationDir, jplPath))
     281           0 :                             return CERTIFICATE_VERIFICATION_FAILED;
     282           0 :                         r = uninstallPlugin(destinationDir);
     283           0 :                         if (r == SUCCESS) {
     284           0 :                             archiver::uncompressArchive(jplPath,
     285             :                                                         destinationDir,
     286             :                                                         PluginUtils::uncompressJplFunction);
     287             :                         }
     288           0 :                     } else if (version == installedVersion) {
     289           0 :                         r = PLUGIN_ALREADY_INSTALLED;
     290             :                     } else {
     291           0 :                         r = PLUGIN_OLD_VERSION;
     292             :                     }
     293           0 :                 }
     294             :             } else {
     295           5 :                 archiver::uncompressArchive(jplPath,
     296             :                                             destinationDir,
     297             :                                             PluginUtils::uncompressJplFunction);
     298             :             }
     299           7 :             if (!libjami::getPluginsEnabled()) {
     300           0 :                 libjami::setPluginsEnabled(true);
     301           0 :                 Manager::instance().saveConfig();
     302           0 :                 loadPlugins();
     303           0 :                 return r;
     304             :             }
     305           7 :             libjami::loadPlugin(destinationDir);
     306           7 :         } catch (const std::exception& e) {
     307           0 :             JAMI_ERR() << e.what();
     308           0 :         }
     309             :     }
     310           7 :     return r;
     311             : }
     312             : 
     313             : int
     314           7 : JamiPluginManager::uninstallPlugin(const std::string& rootPath)
     315             : {
     316           7 :     std::error_code ec;
     317           7 :     if (PluginUtils::checkPluginValidity(rootPath)) {
     318           7 :         auto detailsIt = pluginDetailsMap_.find(rootPath);
     319           7 :         if (detailsIt != pluginDetailsMap_.end()) {
     320           7 :             bool loaded = pm_.checkLoadedPlugin(rootPath);
     321           7 :             if (loaded) {
     322           5 :                 JAMI_INFO() << "PLUGIN: unloading before uninstall.";
     323           5 :                 bool status = libjami::unloadPlugin(rootPath);
     324           5 :                 if (!status) {
     325           0 :                     JAMI_INFO() << "PLUGIN: unable to unload, not performing uninstall.";
     326           0 :                     return FAILURE;
     327             :                 }
     328             :             }
     329          21 :             for (const auto& accId : jami::Manager::instance().getAccountList())
     330          42 :                 std::filesystem::remove_all(fileutils::get_data_dir() / accId
     331          63 :                                      / "plugins" / detailsIt->second.at("id"), ec);
     332           7 :             pluginDetailsMap_.erase(detailsIt);
     333             :         }
     334           7 :         return std::filesystem::remove_all(rootPath, ec) ? SUCCESS : FAILURE;
     335             :     } else {
     336           0 :         JAMI_INFO() << "PLUGIN: not installed.";
     337           0 :         return FAILURE;
     338             :     }
     339             : }
     340             : 
     341             : bool
     342           8 : JamiPluginManager::loadPlugin(const std::string& rootPath)
     343             : {
     344             : #ifdef ENABLE_PLUGIN
     345             :     try {
     346           8 :         bool status = pm_.load(getPluginDetails(rootPath).at("soPath"));
     347           8 :         JAMI_INFO() << "PLUGIN: load status - " << status;
     348             : 
     349           8 :         return status;
     350             : 
     351           0 :     } catch (const std::exception& e) {
     352           0 :         JAMI_ERR() << e.what();
     353           0 :         return false;
     354           0 :     }
     355             : #endif
     356             :     return false;
     357             : }
     358             : 
     359             : bool
     360          10 : JamiPluginManager::loadPlugins()
     361             : {
     362             : #ifdef ENABLE_PLUGIN
     363          10 :     bool status = true;
     364          10 :     auto loadedPlugins = jami::Manager::instance().pluginPreferences.getLoadedPlugins();
     365          11 :     for (const auto& pluginPath : loadedPlugins) {
     366           1 :         status &= loadPlugin(pluginPath);
     367             :     }
     368          10 :     return status;
     369             : #endif
     370             :     return false;
     371          10 : }
     372             : 
     373             : bool
     374           7 : JamiPluginManager::unloadPlugin(const std::string& rootPath)
     375             : {
     376             : #ifdef ENABLE_PLUGIN
     377             :     try {
     378           7 :         bool status = pm_.unload(getPluginDetails(rootPath).at("soPath"));
     379           7 :         JAMI_INFO() << "PLUGIN: unload status - " << status;
     380             : 
     381           7 :         return status;
     382           0 :     } catch (const std::exception& e) {
     383           0 :         JAMI_ERR() << e.what();
     384           0 :         return false;
     385           0 :     }
     386             : #endif
     387             :     return false;
     388             : }
     389             : 
     390             : std::vector<std::string>
     391           4 : JamiPluginManager::getLoadedPlugins() const
     392             : {
     393           4 :     std::vector<std::string> loadedSoPlugins = pm_.getLoadedPlugins();
     394           4 :     std::vector<std::string> loadedPlugins {};
     395           4 :     loadedPlugins.reserve(loadedSoPlugins.size());
     396           4 :     std::transform(loadedSoPlugins.begin(),
     397             :                    loadedSoPlugins.end(),
     398             :                    std::back_inserter(loadedPlugins),
     399           2 :                    [](const std::string& soPath) {
     400           4 :                        return PluginUtils::getRootPathFromSoPath(soPath).string();
     401             :                    });
     402           8 :     return loadedPlugins;
     403           4 : }
     404             : 
     405             : std::vector<std::map<std::string, std::string>>
     406           2 : JamiPluginManager::getPluginPreferences(const std::string& rootPath, const std::string& accountId)
     407             : {
     408           2 :     return PluginPreferencesUtils::getPreferences(rootPath, accountId);
     409             : }
     410             : 
     411             : bool
     412           2 : JamiPluginManager::setPluginPreference(const std::filesystem::path& rootPath,
     413             :                                        const std::string& accountId,
     414             :                                        const std::string& key,
     415             :                                        const std::string& value)
     416             : {
     417           2 :     std::string acc = accountId;
     418             : 
     419             :     // If we try to change a preference value linked to an account
     420             :     // but that preference is global, we must ignore accountId and
     421             :     // change the preference for every account
     422           2 :     if (!accountId.empty()) {
     423             :         // Get global preferences
     424           2 :         auto preferences = PluginPreferencesUtils::getPreferences(rootPath, "");
     425             :         // Check if the preference we want to change is global
     426           1 :         auto it = std::find_if(preferences.cbegin(),
     427             :                                preferences.cend(),
     428           1 :                                [key](const std::map<std::string, std::string>& preference) {
     429           1 :                                    return preference.at("key") == key;
     430             :                                });
     431             :         // Ignore accountId if global preference
     432           1 :         if (it != preferences.cend())
     433           0 :             acc.clear();
     434           1 :     }
     435             : 
     436             :     std::map<std::string, std::string> pluginUserPreferencesMap
     437           2 :         = PluginPreferencesUtils::getUserPreferencesValuesMap(rootPath, acc);
     438             :     std::map<std::string, std::string> pluginPreferencesMap
     439           2 :         = PluginPreferencesUtils::getPreferencesValuesMap(rootPath, acc);
     440             : 
     441             :     // If any plugin handler is active we may have to reload it
     442           2 :     bool force {pm_.checkLoadedPlugin(rootPath.string())};
     443             : 
     444             :     // We check if the preference is modified without having to reload plugin
     445           2 :     force &= preferencesm_.setPreference(key, value, rootPath.string(), acc);
     446           2 :     force &= callsm_.setPreference(key, value, rootPath.string());
     447           2 :     force &= chatsm_.setPreference(key, value, rootPath.string());
     448             : 
     449           2 :     if (force)
     450           0 :         unloadPlugin(rootPath.string());
     451             : 
     452             :     // Save preferences.msgpack with modified preferences values
     453           2 :     auto find = pluginPreferencesMap.find(key);
     454           2 :     if (find != pluginPreferencesMap.end()) {
     455           2 :         pluginUserPreferencesMap[key] = value;
     456             :         auto preferencesValuesFilePath
     457           2 :             = PluginPreferencesUtils::valuesFilePath(rootPath, acc);
     458           2 :         std::lock_guard guard(dhtnet::fileutils::getFileLock(preferencesValuesFilePath));
     459           2 :         std::ofstream fs(preferencesValuesFilePath, std::ios::binary);
     460           2 :         if (!fs.good()) {
     461           0 :             if (force) {
     462           0 :                 loadPlugin(rootPath.string());
     463             :             }
     464           0 :             return false;
     465             :         }
     466             :         try {
     467           2 :             msgpack::pack(fs, pluginUserPreferencesMap);
     468           0 :         } catch (const std::exception& e) {
     469           0 :             JAMI_ERR() << e.what();
     470           0 :             if (force) {
     471           0 :                 loadPlugin(rootPath.string());
     472             :             }
     473           0 :             return false;
     474           0 :         }
     475           2 :     }
     476           2 :     if (force) {
     477           0 :         loadPlugin(rootPath.string());
     478             :     }
     479           2 :     return true;
     480           2 : }
     481             : 
     482             : std::map<std::string, std::string>
     483          14 : JamiPluginManager::getPluginPreferencesValuesMap(const std::string& rootPath,
     484             :                                                  const std::string& accountId)
     485             : {
     486          14 :     return PluginPreferencesUtils::getPreferencesValuesMap(rootPath, accountId);
     487             : }
     488             : 
     489             : bool
     490           3 : JamiPluginManager::resetPluginPreferencesValuesMap(const std::string& rootPath,
     491             :                                                    const std::string& accountId)
     492             : {
     493           3 :     bool acc {accountId.empty()};
     494           3 :     bool loaded {pm_.checkLoadedPlugin(rootPath)};
     495           3 :     if (loaded && acc)
     496           0 :         unloadPlugin(rootPath);
     497           3 :     auto status = PluginPreferencesUtils::resetPreferencesValuesMap(rootPath, accountId);
     498           3 :     preferencesm_.resetPreferences(rootPath, accountId);
     499           3 :     if (loaded && acc) {
     500           0 :         loadPlugin(rootPath);
     501             :     }
     502           3 :     return status;
     503             : }
     504             : 
     505             : void
     506          33 : JamiPluginManager::registerServices()
     507             : {
     508             :     // Register getPluginPreferences so that plugin's can receive it's preferences
     509          33 :     pm_.registerService("getPluginPreferences", [](const DLPlugin* plugin, void* data) {
     510           0 :         auto ppp = static_cast<std::map<std::string, std::string>*>(data);
     511           0 :         *ppp = PluginPreferencesUtils::getPreferencesValuesMap(
     512           0 :             PluginUtils::getRootPathFromSoPath(plugin->getPath()));
     513           0 :         return SUCCESS;
     514             :     });
     515             : 
     516             :     // Register getPluginDataPath so that plugin's can receive the path to it's data folder
     517          33 :     pm_.registerService("getPluginDataPath", [](const DLPlugin* plugin, void* data) {
     518           8 :         auto dataPath = static_cast<std::string*>(data);
     519           8 :         dataPath->assign(PluginUtils::dataPath(plugin->getPath()).string());
     520           8 :         return SUCCESS;
     521             :     });
     522             : 
     523             :     // getPluginAccPreferences is a service that allows plugins to load saved per account preferences.
     524           0 :     auto getPluginAccPreferences = [](const DLPlugin* plugin, void* data) {
     525           0 :         const auto path = PluginUtils::getRootPathFromSoPath(plugin->getPath());
     526           0 :         auto preferencesPtr {(static_cast<PreferencesMap*>(data))};
     527           0 :         if (!preferencesPtr)
     528           0 :             return FAILURE;
     529             : 
     530           0 :         preferencesPtr->emplace("default",
     531           0 :                                 PluginPreferencesUtils::getPreferencesValuesMap(path, "default"));
     532             : 
     533           0 :         for (const auto& accId : jami::Manager::instance().getAccountList())
     534           0 :             preferencesPtr->emplace(accId,
     535           0 :                                     PluginPreferencesUtils::getPreferencesValuesMap(path, accId));
     536           0 :         return SUCCESS;
     537           0 :     };
     538             : 
     539          33 :     pm_.registerService("getPluginAccPreferences", getPluginAccPreferences);
     540          33 : }
     541             : 
     542             : void
     543           1 : JamiPluginManager::addPluginAuthority(const dht::crypto::Certificate& cert)
     544             : {
     545           1 :     trust_.add(cert);
     546           1 : }
     547             : } // namespace jami

Generated by: LCOV version 1.14