mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-07 22:02:12 +08:00
plugin: add editable preference
Change-Id: I61c074464e21344b2d7a1d64023f23bd96139c3b
This commit is contained in:
@ -154,5 +154,16 @@
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="addValueToPreference" tp:name-for-bindings="addValueToPreference">
|
||||
<tp:added version="9.6.0"/>
|
||||
<arg type="s" name="pluginId" direction="in">
|
||||
</arg>
|
||||
<arg type="s" name="preferenceKey" direction="in">
|
||||
</arg>
|
||||
<arg type="s" name="value" direction="in">
|
||||
</arg>
|
||||
<arg type="b" name="status" direction="out">
|
||||
</arg>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
|
@ -132,3 +132,11 @@ DBusPluginManagerInterface::getCallMediaHandlerStatus()
|
||||
{
|
||||
return DRing::getCallMediaHandlerStatus();
|
||||
}
|
||||
|
||||
bool
|
||||
DBusPluginManagerInterface::addValueToPreference(const std::string& pluginId,
|
||||
const std::string& preferenceKey,
|
||||
const std::string& value)
|
||||
{
|
||||
return DRing::addValueToPreference(pluginId, preferenceKey, value);
|
||||
}
|
||||
|
@ -71,4 +71,7 @@ class DRING_PUBLIC DBusPluginManagerInterface :
|
||||
bool getPluginsEnabled();
|
||||
void setPluginsEnabled(const bool& state);
|
||||
std::map<std::string,std::string> getCallMediaHandlerStatus();
|
||||
bool addValueToPreference(const std::string& pluginId,
|
||||
const std::string& preferenceKey,
|
||||
const std::string& value);
|
||||
};
|
||||
|
@ -42,4 +42,7 @@ std::map<std::string,std::string> getCallMediaHandlerDetails(const std::string&
|
||||
bool getPluginsEnabled();
|
||||
void setPluginsEnabled(bool state);
|
||||
std::map<std::string,std::string> getCallMediaHandlerStatus();
|
||||
bool addValueToPreference(const std::string& pluginId,
|
||||
const std::string& preferenceKey,
|
||||
const std::string& value);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ dnl Jami - configure.ac for automake 1.9 and autoconf 2.59
|
||||
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ([2.65])
|
||||
AC_INIT([Jami Daemon],[9.5.0],[ring@gnu.org],[jami])
|
||||
AC_INIT([Jami Daemon],[9.6.0],[ring@gnu.org],[jami])
|
||||
|
||||
AC_COPYRIGHT([[Copyright (c) Savoir-faire Linux 2004-2020]])
|
||||
AC_REVISION([$Revision$])
|
||||
|
@ -1,5 +1,5 @@
|
||||
project('jami-daemon', ['c', 'cpp'],
|
||||
version: '9.5.0',
|
||||
version: '9.6.0',
|
||||
license: 'GPL3+',
|
||||
default_options: ['cpp_std=gnu++17', 'buildtype=debugoptimized'],
|
||||
meson_version:'>= 0.54'
|
||||
|
@ -144,4 +144,14 @@ getCallMediaHandlerStatus()
|
||||
.getCallServicesManager()
|
||||
.getCallMediaHandlerStatus();
|
||||
}
|
||||
|
||||
bool
|
||||
addValueToPreference(const std::string& pluginId,
|
||||
const std::string& preferenceKey,
|
||||
const std::string& value)
|
||||
{
|
||||
return jami::Manager::instance().getJamiPluginManager().addValueToPreference(pluginId,
|
||||
preferenceKey,
|
||||
value);
|
||||
}
|
||||
} // namespace DRing
|
||||
|
@ -53,4 +53,7 @@ DRING_PUBLIC std::map<std::string,std::string> getCallMediaHandlerDetails(const
|
||||
DRING_PUBLIC bool getPluginsEnabled();
|
||||
DRING_PUBLIC void setPluginsEnabled(bool state);
|
||||
DRING_PUBLIC std::map<std::string,std::string> getCallMediaHandlerStatus();
|
||||
DRING_PUBLIC bool addValueToPreference(const std::string& pluginId,
|
||||
const std::string& preferenceKey,
|
||||
const std::string& value);
|
||||
}
|
||||
|
@ -1023,5 +1023,35 @@ accessFile(const std::string& file, int mode)
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string
|
||||
getFileName(const std::string& filePath)
|
||||
{
|
||||
std::string fileName = filePath;
|
||||
const size_t last_slash_idx = fileName.find_last_of(DIR_SEPARATOR_STR_ESC);
|
||||
if (std::string::npos != last_slash_idx) {
|
||||
fileName.erase(0, last_slash_idx + 1);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
std::string
|
||||
removeExtension(const std::string& filePath)
|
||||
{
|
||||
std::string fileName = filePath;
|
||||
const size_t period_idx = fileName.rfind('.');
|
||||
if (std::string::npos != period_idx) {
|
||||
fileName.erase(period_idx);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
std::string
|
||||
getExtension(const std::string& filePath)
|
||||
{
|
||||
std::string fileExt = filePath;
|
||||
fileExt = fileExt.substr(fileExt.find_last_of('.'));
|
||||
return fileExt;
|
||||
}
|
||||
|
||||
} // namespace jami
|
||||
} // namespace fileutils
|
||||
|
@ -176,6 +176,10 @@ std::string md5sum(const std::vector<uint8_t>& buffer);
|
||||
*/
|
||||
int accessFile(const std::string& file, int mode);
|
||||
|
||||
std::string getFileName(const std::string& filePath);
|
||||
std::string removeExtension(const std::string& filePath);
|
||||
std::string getExtension(const std::string& filePath);
|
||||
|
||||
} // namespace fileutils
|
||||
} // namespace jami
|
||||
|
||||
|
@ -34,6 +34,7 @@ extern "C" {
|
||||
#include <archive.h>
|
||||
}
|
||||
|
||||
#include "fileutils.h"
|
||||
#include <json/json.h>
|
||||
#include <msgpack.hpp>
|
||||
|
||||
@ -337,11 +338,10 @@ JamiPluginManager::unloadPlugin(const std::string& rootPath)
|
||||
void
|
||||
JamiPluginManager::togglePlugin(const std::string& rootPath, bool toggle)
|
||||
{
|
||||
//This function should not be used as is
|
||||
//One should modify it to perform plugin install followed by load
|
||||
//rootPath should be the jplpath!
|
||||
try
|
||||
{
|
||||
// This function should not be used as is
|
||||
// One should modify it to perform plugin install followed by load
|
||||
// rootPath should be the jplpath!
|
||||
try {
|
||||
std::string soPath = getPluginDetails(rootPath).at("soPath");
|
||||
// remove the previous plugin object if it was registered
|
||||
pm_.destroyPluginComponents(soPath);
|
||||
@ -372,6 +372,8 @@ std::vector<std::map<std::string, std::string>>
|
||||
JamiPluginManager::getPluginPreferences(const std::string& rootPath)
|
||||
{
|
||||
const std::string preferenceFilePath = getPreferencesConfigFilePath(rootPath);
|
||||
std::map<std::string, std::map<std::string, std::string>> userPreferences
|
||||
= getUserPreferencesValuesMap(rootPath);
|
||||
std::ifstream file(preferenceFilePath);
|
||||
Json::Value root;
|
||||
Json::CharReaderBuilder rbuilder;
|
||||
@ -389,11 +391,34 @@ JamiPluginManager::getPluginPreferences(const std::string& rootPath)
|
||||
std::string key = jsonPreference.get("key", "None").asString();
|
||||
if (type != "None" && key != "None") {
|
||||
if (keys.find(key) == keys.end()) {
|
||||
const auto& preferenceAttributes = parsePreferenceConfig(jsonPreference,
|
||||
type);
|
||||
std::map<std::string, std::string> preferenceAttributes
|
||||
= parsePreferenceConfig(jsonPreference, type);
|
||||
// If the parsing of the attributes was successful, commit the map and the key
|
||||
if (!preferenceAttributes.empty()) {
|
||||
preferences.push_back(std::move(preferenceAttributes));
|
||||
if (!userPreferences[key].empty()) {
|
||||
preferenceAttributes["entryValues"]
|
||||
= userPreferences[key]["entryValues"];
|
||||
preferenceAttributes["entries"] = userPreferences[key]["entries"];
|
||||
}
|
||||
|
||||
preferenceAttributes["entryValues"]
|
||||
= std::regex_replace(preferenceAttributes["entryValues"],
|
||||
std::regex("\\["),
|
||||
"$2");
|
||||
preferenceAttributes["entryValues"]
|
||||
= std::regex_replace(preferenceAttributes["entryValues"],
|
||||
std::regex("\\]"),
|
||||
"$2");
|
||||
preferenceAttributes["entries"]
|
||||
= std::regex_replace(preferenceAttributes["entries"],
|
||||
std::regex("\\["),
|
||||
"$2");
|
||||
preferenceAttributes["entries"]
|
||||
= std::regex_replace(preferenceAttributes["entries"],
|
||||
std::regex("\\]"),
|
||||
"$2");
|
||||
|
||||
preferences.emplace_back(std::move(preferenceAttributes));
|
||||
keys.insert(key);
|
||||
}
|
||||
}
|
||||
@ -443,6 +468,41 @@ JamiPluginManager::getPluginUserPreferencesValuesMap(const std::string& rootPath
|
||||
return rmap;
|
||||
}
|
||||
|
||||
std::map<std::string, std::map<std::string, std::string>>
|
||||
JamiPluginManager::getUserPreferencesValuesMap(const std::string& rootPath)
|
||||
{
|
||||
const std::string preferencesValuesFilePath = pluginAddedPreferencesValuesFilePath(rootPath);
|
||||
std::ifstream file(preferencesValuesFilePath, std::ios::binary);
|
||||
std::map<std::string, std::map<std::string, std::string>> rmap;
|
||||
|
||||
// If file is accessible
|
||||
if (file.good()) {
|
||||
std::lock_guard<std::mutex> guard(fileutils::getFileLock(preferencesValuesFilePath));
|
||||
// Get file size
|
||||
std::string str;
|
||||
file.seekg(0, std::ios::end);
|
||||
size_t fileSize = static_cast<size_t>(file.tellg());
|
||||
// If not empty
|
||||
if (fileSize > 0) {
|
||||
// Read whole file content and put it in the string str
|
||||
str.reserve(static_cast<size_t>(file.tellg()));
|
||||
file.seekg(0, std::ios::beg);
|
||||
str.assign((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||
file.close();
|
||||
try {
|
||||
// Unpack the string
|
||||
msgpack::object_handle oh = msgpack::unpack(str.data(), str.size());
|
||||
// Deserialized object is valid during the msgpack::object_handle instance is alive.
|
||||
msgpack::object deserialized = oh.get();
|
||||
deserialized.convert(rmap);
|
||||
} catch (const std::exception& e) {
|
||||
JAMI_ERR() << e.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
return rmap;
|
||||
}
|
||||
|
||||
bool
|
||||
JamiPluginManager::setPluginPreference(const std::string& rootPath,
|
||||
const std::string& key,
|
||||
@ -521,6 +581,69 @@ JamiPluginManager::resetPluginPreferencesValuesMap(const std::string& rootPath)
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
bool
|
||||
JamiPluginManager::copyFileToPluginData(const std::string& pluginId,
|
||||
const std::string& value,
|
||||
const std::string& preferenceCategory,
|
||||
std::string& fileName,
|
||||
std::string& fileExt)
|
||||
{
|
||||
if (!fileutils::isFile(value))
|
||||
return false;
|
||||
|
||||
const std::string destinationDir {pluginId + DIR_SEPARATOR_CH + "data" + DIR_SEPARATOR_CH
|
||||
+ preferenceCategory + DIR_SEPARATOR_CH};
|
||||
fileName = fileutils::removeExtension(fileutils::getFileName(value));
|
||||
fileExt = fileutils::getExtension(value);
|
||||
|
||||
auto srcData = fileutils::loadFile(value);
|
||||
|
||||
if (fileutils::isFile(destinationDir + fileName + fileExt)) {
|
||||
fileutils::saveFile(destinationDir + fileName + fileExt, srcData);
|
||||
return false;
|
||||
}
|
||||
fileutils::saveFile(destinationDir + fileName + fileExt, srcData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JamiPluginManager::addValueToPreference(const std::string& pluginId,
|
||||
const std::string& preferenceKey,
|
||||
const std::string& value)
|
||||
{
|
||||
std::map<std::string, std::map<std::string, std::string>> userPreferences
|
||||
= getUserPreferencesValuesMap(pluginId);
|
||||
std::vector<std::map<std::string, std::string>> preferences = getPluginPreferences(pluginId);
|
||||
|
||||
for (auto& preference : preferences) {
|
||||
if (preference["key"] == preferenceKey) {
|
||||
std::string fileName, fileExt;
|
||||
if (!copyFileToPluginData(pluginId, value, preference["category"], fileName, fileExt)) {
|
||||
return setPluginPreference(pluginId, preferenceKey, fileName + fileExt);
|
||||
}
|
||||
setPluginPreference(pluginId, preferenceKey, fileName + fileExt);
|
||||
userPreferences[preferenceKey]["entries"] = preference["entries"] + "," + fileName;
|
||||
userPreferences[preferenceKey]["entryValues"] = preference["entryValues"] + ","
|
||||
+ fileName + fileExt;
|
||||
|
||||
const std::string preferencesValuesFilePath = pluginAddedPreferencesValuesFilePath(
|
||||
pluginId);
|
||||
std::ofstream fs(preferencesValuesFilePath, std::ios::binary);
|
||||
if (!fs.good()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
std::lock_guard<std::mutex> guard(fileutils::getFileLock(preferencesValuesFilePath));
|
||||
msgpack::pack(fs, userPreferences);
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
JAMI_ERR() << e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>
|
||||
JamiPluginManager::readPluginManifestFromArchive(const std::string& jplPath)
|
||||
{
|
||||
|
@ -125,6 +125,10 @@ public:
|
||||
|
||||
bool resetPluginPreferencesValuesMap(const std::string& rootPath);
|
||||
|
||||
bool addValueToPreference(const std::string& pluginId,
|
||||
const std::string& preferenceKey,
|
||||
const std::string& value);
|
||||
|
||||
public:
|
||||
CallServicesManager& getCallServicesManager() { return csm_; }
|
||||
|
||||
@ -180,6 +184,13 @@ private:
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> getPluginUserPreferencesValuesMap(const std::string& rootPath);
|
||||
std::map<std::string, std::map<std::string, std::string>> getUserPreferencesValuesMap(
|
||||
const std::string& rootPath);
|
||||
bool copyFileToPluginData(const std::string& pluginId,
|
||||
const std::string& value,
|
||||
const std::string& preferenceCategory,
|
||||
std::string& fileName,
|
||||
std::string& fileExt);
|
||||
|
||||
/**
|
||||
* @brief getPreferencesConfigFilePath
|
||||
@ -205,6 +216,18 @@ private:
|
||||
return rootPath + DIR_SEPARATOR_CH + "preferences.msgpack";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief pluginAddedPreferencesValuesFilePath
|
||||
* Returns the plugin added preferences values file path from the plugin root path
|
||||
* This is entirely defined by how the plugin files are structured
|
||||
* @param plugin rootPath
|
||||
* @return path of the preferences values
|
||||
*/
|
||||
std::string pluginAddedPreferencesValuesFilePath(const std::string& rootPath) const
|
||||
{
|
||||
return rootPath + DIR_SEPARATOR_CH + "addedPreferences.msgpack";
|
||||
}
|
||||
|
||||
void registerServices();
|
||||
|
||||
private:
|
||||
|
@ -40,8 +40,8 @@ public:
|
||||
* The id is the path of the plugin that created this MediaHandler
|
||||
* @return
|
||||
*/
|
||||
std::string id() const { return id_;}
|
||||
virtual void setId(const std::string& id) final {id_ = id;}
|
||||
std::string id() const { return id_; }
|
||||
virtual void setId(const std::string& id) final { id_ = id; }
|
||||
|
||||
private:
|
||||
std::string id_;
|
||||
|
Reference in New Issue
Block a user