summaryrefslogtreecommitdiff
path: root/PluginsManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'PluginsManager.cpp')
-rw-r--r--PluginsManager.cpp932
1 files changed, 932 insertions, 0 deletions
diff --git a/PluginsManager.cpp b/PluginsManager.cpp
new file mode 100644
index 0000000..269e837
--- /dev/null
+++ b/PluginsManager.cpp
@@ -0,0 +1,932 @@
+/** \file PluginsManager.cpp
+\brief Define the class to manage and load the plugins
+\author alpha_one_x86
+\licence GPL3, see the file COPYING */
+
+#include <QDir>
+#include <QMessageBox>
+#include <QFileDialog>
+#include <QFile>
+#include <QFileInfo>
+
+#include <iterator>
+
+#include "PluginsManager.h"
+#include "cpp11addition.h"
+#include "FacilityEngine.h"
+
+/// \brief Create the manager and load the defaults variables
+PluginsManager::PluginsManager()
+{
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ //load the overall instance
+ pluginLoaded = false;
+ language = "en";
+ stopIt = false;
+ pluginInformation = NULL;
+ #ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE
+ importingPlugin = false;
+ #endif
+ editionSemList.release();
+ englishPluginType.push_back("CopyEngine");englishPluginType.push_back("Languages");englishPluginType.push_back("Listener");englishPluginType.push_back("PluginLoader");englishPluginType.push_back("SessionLoader");englishPluginType.push_back("Themes");
+ //catPlugin << tr("CopyEngine") << tr("Languages") << tr("Listener") << tr("PluginLoader") << tr("SessionLoader") << tr("Themes");
+ #ifdef ULTRACOPIER_PLUGIN_IMPORT_SUPPORT
+ connect(&decodeThread, &QXzDecodeThread::decodedIsFinish, this, &PluginsManager::decodingFinished,Qt::QueuedConnection);
+ #endif
+ connect(this, &PluginsManager::finished, this, &PluginsManager::post_operation,Qt::QueuedConnection);
+// connect(this, &PluginsManager::pluginListingIsfinish, options,&OptionEngine::setInterfaceValue);
+ //load the plugins list
+
+ /// \bug bug when I put here: moveToThread(this);, due to the direction connection to remove the plugin
+ start();
+}
+
+/// \brief Destroy the manager
+PluginsManager::~PluginsManager()
+{
+ stopIt=true;
+ if(pluginInformation!=NULL)
+ delete pluginInformation;
+ if(this->isRunning())
+ this->wait(0);
+}
+
+/// \brief set current language
+void PluginsManager::setLanguage(const std::string &language)
+{
+ this->language=language;
+}
+
+void PluginsManager::post_operation()
+{
+ pluginLoaded=true;
+ emit pluginListingIsfinish();
+}
+
+bool PluginsManager::allPluginHaveBeenLoaded() const
+{
+ return pluginLoaded;
+}
+
+void PluginsManager::lockPluginListEdition()
+{
+ editionSemList.acquire();
+}
+
+void PluginsManager::unlockPluginListEdition()
+{
+ editionSemList.release();
+}
+
+void PluginsManager::run()
+{
+ regexp_to_clean_1=std::regex("[\n\r]+");
+ regexp_to_clean_2=std::regex("[ \t]+");
+ regexp_to_clean_3=std::regex("(&&)+");
+ regexp_to_clean_4=std::regex("^&&");
+ regexp_to_clean_5=std::regex("&&$");
+ regexp_to_dep_1=std::regex("(&&|\\|\\||\\(|\\))");
+ regexp_to_dep_2=std::regex("^(<=|<|=|>|>=)[a-zA-Z0-9\\-]+-([0-9]+\\.)*[0-9]+$");
+ regexp_to_dep_3=std::regex("(<=|<|=|>|>=)");
+ regexp_to_dep_4=std::regex("-([0-9]+\\.)*[0-9]+");
+ regexp_to_dep_5=std::regex("[a-zA-Z0-9\\-]+-");
+ regexp_to_dep_6=std::regex("[a-zA-Z0-9\\-]+-([0-9]+\\.)*[0-9]+");
+
+ //load the path and plugins into the path
+ const std::string &separator=FacilityEngine::separator();
+ std::vector<std::string> readPath;
+ readPath=ResourcesManager::resourcesManager->getReadPath();
+ pluginsList.clear();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"pluginsList.size(): "+std::to_string(pluginsList.size()));
+ foreach(std::string basePath,readPath)
+ {
+ foreach(std::string dirSub,englishPluginType)
+ {
+ std::string pluginComposed=basePath+dirSub+separator;
+ QDir dir(QString::fromStdString(pluginComposed));
+ if(stopIt)
+ return;
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"search plugin into: "+pluginComposed);
+ if(dir.exists())
+ {
+ foreach(QString dirName, dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot))
+ {
+ if(stopIt)
+ return;
+ loadPluginInformation(pluginComposed+dirName.toStdString()+separator);
+ }
+ }
+ }
+ }
+ #ifdef ULTRACOPIER_DEBUG
+ unsigned int index_debug=0;
+ while(index_debug<pluginsList.size())
+ {
+ std::string category=categoryToString(pluginsList.at(index_debug).category);
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"Plugin "+std::to_string(index_debug)+" loaded ("+category+"): "+pluginsList.at(index_debug).path);
+ index_debug++;
+ }
+ #endif
+ #ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE
+ while(checkDependencies()!=0){};
+ #endif
+ //QList<PluginsAvailable> list;
+ unsigned int index=0;
+ while(index<pluginsList.size())
+ {
+ if(pluginsList.at(index).errorString.empty())
+ emit onePluginAdded(pluginsList.at(index));
+ index++;
+ }
+}
+
+std::string PluginsManager::categoryToString(const PluginType &category) const
+{
+ switch(category)
+ {
+ case PluginType_CopyEngine:
+ return "CopyEngine";
+ break;
+ case PluginType_Languages:
+ return "Languages";
+ break;
+ case PluginType_Listener:
+ return "Listener";
+ break;
+ case PluginType_PluginLoader:
+ return "PluginLoader";
+ break;
+ case PluginType_SessionLoader:
+ return "SessionLoader";
+ break;
+ case PluginType_Themes:
+ return "Themes";
+ break;
+ default:
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"cat text not found: "+std::to_string(category));
+ return "Unknown";
+ break;
+ }
+}
+
+std::string PluginsManager::categoryToTranslation(const PluginType &category)
+{
+ if(pluginInformation==NULL)
+ {
+ pluginInformation=new PluginInformation();
+ connect(this, &PluginsManager::newLanguageLoaded, pluginInformation, &PluginInformation::retranslateInformation,Qt::QueuedConnection);
+ }
+ return pluginInformation->categoryToTranslation(category);
+}
+
+bool PluginsManager::isSamePlugin(const PluginsAvailable &pluginA,const PluginsAvailable &pluginB)
+{
+ /*if(pluginA.category!=pluginB.category)
+ return false;*/
+ //only this test should be suffisent
+ if(pluginA.path!=pluginB.path)
+ return false;
+ /*if(pluginA.name!=pluginB.name)
+ return false;
+ if(pluginA.writablePath!=pluginB.writablePath)
+ return false;
+ if(pluginA.categorySpecific!=pluginB.categorySpecific)
+ return false;
+ if(pluginA.version!=pluginB.version)
+ return false;
+ if(pluginA.informations!=pluginB.informations)
+ return false;*/
+ return true;
+}
+
+bool PluginsManager::loadPluginInformation(const std::string &path)
+{
+ PluginsAvailable tempPlugin;
+ tempPlugin.isAuth = false;
+ tempPlugin.path = path;
+ tempPlugin.category = PluginType_Unknow;
+ QDir pluginPath(QString::fromStdString(path));
+ if(pluginPath.cdUp() && pluginPath.cdUp() &&
+ !ResourcesManager::resourcesManager->getWritablePath().empty() &&
+ pluginPath==QDir(QString::fromStdString(ResourcesManager::resourcesManager->getWritablePath())))
+ tempPlugin.isWritable=true;
+ else
+ tempPlugin.isWritable=false;
+ QFile xmlMetaData(QString::fromStdString(path)+"informations.xml");
+ if(xmlMetaData.exists())
+ {
+ if(xmlMetaData.open(QIODevice::ReadOnly))
+ {
+ loadPluginXml(&tempPlugin,xmlMetaData.readAll());
+ xmlMetaData.close();
+ }
+ else
+ {
+ tempPlugin.errorString=tr("informations.xml is not accessible").toStdString();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"informations.xml is not accessible into the plugin: "+path);
+ }
+ }
+ else
+ {
+ tempPlugin.errorString=tr("informations.xml not found for the plugin").toStdString();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"informations.xml not found for the plugin: "+path);
+ }
+ editionSemList.acquire();
+ pluginsList.push_back(tempPlugin);
+ if(tempPlugin.errorString.empty())
+ pluginsListIndexed[tempPlugin.category].push_back(tempPlugin);
+ editionSemList.release();
+ if(tempPlugin.errorString.empty())
+ return true;
+ else
+ {
+ emit onePluginInErrorAdded(tempPlugin);
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Error detected, the not loaded: "+tempPlugin.errorString+", for path: "+tempPlugin.path);
+ return false;
+ }
+}
+
+void PluginsManager::loadPluginXml(PluginsAvailable * thePlugin,const QByteArray &xml)
+{
+ QString errorStr;
+ int errorLine;
+ int errorColumn;
+ QDomDocument domDocument;
+ if (!domDocument.setContent(xml, false, &errorStr,&errorLine,&errorColumn))
+ {
+ thePlugin->errorString=tr("%1, parse error at line %2, column %3: %4").arg("informations.xml").arg(errorLine).arg(errorColumn).arg(errorStr).toStdString();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"informations.xml, Parse error at line "+std::to_string(errorLine)+", column "+std::to_string(errorColumn)+": "+errorStr.toStdString());
+ }
+ else
+ {
+ QDomElement root = domDocument.documentElement();
+ if (root.tagName() != QStringLiteral("package"))
+ {
+ thePlugin->errorString=tr("\"package\" root tag not found for the xml file").toStdString();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"\"package\" root balise not found for the xml file");
+ }
+ //load the variable
+ if(thePlugin->errorString.empty())
+ loadBalise(root,"title",&(thePlugin->informations),&(thePlugin->errorString),true,true,true);
+ if(thePlugin->errorString.empty())
+ loadBalise(root,"website",&(thePlugin->informations),&(thePlugin->errorString),false,true);
+ if(thePlugin->errorString.empty())
+ loadBalise(root,"description",&(thePlugin->informations),&(thePlugin->errorString),true,true,true);
+ if(thePlugin->errorString.empty())
+ loadBalise(root,"author",&(thePlugin->informations),&(thePlugin->errorString),true,false);
+ if(thePlugin->errorString.empty())
+ loadBalise(root,"pubDate",&(thePlugin->informations),&(thePlugin->errorString),true,false);
+ if(thePlugin->errorString.empty())
+ {
+ loadBalise(root,"version",&(thePlugin->informations),&(thePlugin->errorString),true,false);
+ if(thePlugin->errorString.empty())
+ thePlugin->version=thePlugin->informations.back().back();
+ }
+ if(thePlugin->errorString.empty())
+ {
+ loadBalise(root,"category",&(thePlugin->informations),&(thePlugin->errorString),true,false);
+ if(thePlugin->errorString.empty())
+ {
+ std::string tempCat=thePlugin->informations.back().back();
+ if(tempCat=="Languages")
+ thePlugin->category=PluginType_Languages;
+ else if(tempCat=="CopyEngine")
+ thePlugin->category=PluginType_CopyEngine;
+ else if(tempCat=="Listener")
+ thePlugin->category=PluginType_Listener;
+ else if(tempCat=="PluginLoader")
+ thePlugin->category=PluginType_PluginLoader;
+ else if(tempCat=="SessionLoader")
+ thePlugin->category=PluginType_SessionLoader;
+ else if(tempCat=="Themes")
+ thePlugin->category=PluginType_Themes;
+ else
+ thePlugin->errorString="Unknow category: "+std::to_string((int)thePlugin->category);
+ if(thePlugin->errorString.empty())
+ {
+ if(thePlugin->category!=PluginType_Languages)
+ {
+ #ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE
+ loadBalise(root,"architecture",&(thePlugin->informations),&(thePlugin->errorString),true,false);
+ if(thePlugin->errorString.empty())
+ {
+ if(thePlugin->informations.back().back()!=ULTRACOPIER_PLATFORM_CODE)
+ thePlugin->errorString="Wrong platform code: "+thePlugin->informations.back().back();
+ }
+ #endif
+ }
+ }
+ }
+ }
+ if(thePlugin->errorString.empty())
+ {
+ loadBalise(root,"name",&(thePlugin->informations),&(thePlugin->errorString),true,false);
+ if(thePlugin->errorString.empty())
+ {
+ thePlugin->name=thePlugin->informations.back().back();
+ size_t index=0;
+ while(index<pluginsList.size())
+ {
+ size_t sub_index=0;
+ while(sub_index<pluginsList.at(index).informations.size())
+ {
+ if(pluginsList.at(index).informations.at(sub_index).front()=="name" &&
+ pluginsList.at(index).name==thePlugin->name &&
+ pluginsList.at(index).category==thePlugin->category)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Plugin duplicate found ("+std::to_string((int)thePlugin->category)+"/"+pluginsList.at(index).informations.at(sub_index).back()+"), already loaded, actual version skipped: "+thePlugin->version);
+ thePlugin->errorString=tr("Duplicated plugin found, already loaded!").toStdString();
+ break;
+ break;
+ }
+ sub_index++;
+ }
+ index++;
+ }
+ }
+ }
+ if(thePlugin->errorString.empty())
+ loadBalise(root,"dependencies",&(thePlugin->informations),&(thePlugin->errorString),true,false);
+ if(thePlugin->errorString.empty())
+ {
+ QDomElement child = root.firstChildElement("categorySpecific");
+ if(!child.isNull() && child.isElement())
+ thePlugin->categorySpecific=child;
+ }
+ }
+}
+
+/// \brief to load the multi-language balise
+void PluginsManager::loadBalise(const QDomElement &root,const std::string &name,std::vector<std::vector<std::string> > *informations,std::string *errorString,bool needHaveOneEntryMinimum,bool multiLanguage,bool englishNeedBeFound)
+{
+ int foundElement=0;
+ bool englishTextIsFoundForThisChild=false;
+ QDomElement child = root.firstChildElement(QString::fromStdString(name));
+ while(!child.isNull())
+ {
+ if(child.isElement())
+ {
+ std::vector<std::string> newInformations;
+ if(multiLanguage)
+ {
+ if(child.hasAttribute(QStringLiteral("xml:lang")))
+ {
+ if(child.attribute(QStringLiteral("xml:lang"))==QStringLiteral("en"))
+ englishTextIsFoundForThisChild=true;
+ foundElement++;
+ newInformations.push_back(child.tagName().toStdString());
+ newInformations.push_back(child.attribute(QStringLiteral("xml:lang")).toStdString());
+ newInformations.push_back(child.text().toStdString());
+ }
+ else
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Have not the attribute xml:lang: child.tagName(): "+child.tagName().toStdString()+", child.text(): "+child.text().toStdString());
+ }
+ else
+ {
+ foundElement++;
+ newInformations.push_back(child.tagName().toStdString());
+ newInformations.push_back(child.text().toStdString());
+ }
+ informations->push_back(newInformations);
+ }
+ else
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Is not Element: child.tagName(): "+child.tagName().toStdString());
+ child = child.nextSiblingElement(QString::fromStdString(name));
+ }
+ if(multiLanguage && englishTextIsFoundForThisChild==false && englishNeedBeFound)
+ {
+ informations->clear();
+ *errorString=tr("English text missing in the informations.xml for the tag: %1").arg(QString::fromStdString(name)).toStdString();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"English text missing into the informations.xml for the tag: "+name);
+ return;
+ }
+ if(needHaveOneEntryMinimum && foundElement==0)
+ {
+ informations->clear();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Tag not found: "+name);
+ *errorString=tr("Tag not found: %1").arg(QString::fromStdString(name)).toStdString();
+ }
+}
+
+/// \brief to load the get dom specific
+std::string PluginsManager::getDomSpecific(const QDomElement &root,const std::string &name,const std::vector<std::pair<std::string,std::string> > &listChildAttribute) const
+{
+ QDomElement child = root.firstChildElement(QString::fromStdString(name));
+ bool allIsFound;
+ while(!child.isNull())
+ {
+ if(child.isElement())
+ {
+ allIsFound=true;
+ size_t index=0;
+ while(index<listChildAttribute.size())
+ {
+ const std::pair<std::string,std::string> &entry=listChildAttribute.at(index);
+ if(child.attribute(QString::fromStdString(entry.first))!=QString::fromStdString(entry.second))
+ {
+ allIsFound=false;
+ break;
+ }
+ index++;
+ }
+ if(allIsFound)
+ return child.text().toStdString();
+ }
+ else
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Is not Element: child.tagName(): "+child.tagName().toStdString());
+ child = child.nextSiblingElement(QString::fromStdString(name));
+ }
+ return std::string();
+}
+
+/// \brief to load the get dom specific
+std::string PluginsManager::getDomSpecific(const QDomElement &root,const std::string &name) const
+{
+ QDomElement child = root.firstChildElement(QString::fromStdString(name));
+ while(!child.isNull())
+ {
+ if(child.isElement())
+ return child.text().toStdString();
+ else
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Is not Element: child.tagName(): "+child.tagName().toStdString());
+ child = child.nextSiblingElement(QString::fromStdString(name));
+ }
+ return std::string();
+}
+
+#ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE
+/// \brief check the dependencies
+uint32_t PluginsManager::checkDependencies()
+{
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ uint32_t errors=0;
+ unsigned int index=0;
+ bool depCheck;
+ while(index<pluginsList.size())
+ {
+ unsigned int sub_index=0;
+ while(sub_index<pluginsList.at(index).informations.size())
+ {
+ if(pluginsList.at(index).informations.at(sub_index).size()==2 && pluginsList.at(index).informations.at(sub_index).at(0)=="dependencies")
+ {
+ std::string dependencies = pluginsList.at(index).informations.at(sub_index).at(1);
+ dependencies=std::regex_replace(dependencies, regexp_to_clean_1,"&&");
+ dependencies=std::regex_replace(dependencies, regexp_to_clean_2,"");
+ dependencies=std::regex_replace(dependencies, regexp_to_clean_3,"&&");
+ dependencies=std::regex_replace(dependencies, regexp_to_clean_4,"");
+ dependencies=std::regex_replace(dependencies, regexp_to_clean_5,"");
+ std::sregex_token_iterator iter(dependencies.begin(), dependencies.end(), regexp_to_dep_1, -1), end;
+ for ( ; iter != end; ++iter)
+ {
+ std::string dependenciesToParse=trim(*iter);
+ if(dependenciesToParse.empty()) {
+ continue;
+ }
+ if(!std::regex_match(dependenciesToParse, regexp_to_dep_2))
+ {
+ pluginsList[index].informations.clear();
+ pluginsList[index].errorString=tr("Dependencies part is wrong").toStdString();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Dependencies part is wrong: "+dependenciesToParse);
+ emit onePluginInErrorAdded(pluginsList.at(index));
+ errors++;
+ break;
+ }
+ std::string partName=dependenciesToParse;
+ partName=std::regex_replace(partName, regexp_to_dep_3, "");
+ partName=std::regex_replace(partName, regexp_to_dep_4, "");
+ std::string partVersion=dependenciesToParse;
+ partVersion=std::regex_replace(partVersion, regexp_to_dep_3, "");
+ partVersion=std::regex_replace(partVersion, regexp_to_dep_5, "");
+ std::string partComp=dependenciesToParse;
+ partComp=std::regex_replace(partComp, regexp_to_dep_6, "");
+ //current version soft
+ std::string pluginVersion=getPluginVersion(partName);
+ depCheck=compareVersion(pluginVersion,partComp,partVersion);
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"dependencies to resolv, partName: "+partName+", partVersion: "+partVersion+", partComp: "+partComp+", pluginVersion: "+pluginVersion+", depCheck: "+std::to_string(depCheck));
+ if(!depCheck)
+ {
+ pluginsList[index].informations.clear();
+ pluginsList[index].errorString=tr("Dependencies %1 are not satisfied, for plugin: %2").arg(QString::fromStdString(dependenciesToParse)).arg(QString::fromStdString(pluginsList[index].path)).toStdString();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Dependencies "+dependenciesToParse+" are not satisfied, for plugin: "+pluginsList[index].path);
+ pluginsListIndexed.erase(pluginsListIndexed.find(pluginsList.at(index).category));
+ emit onePluginInErrorAdded(pluginsList.at(index));
+ errors++;
+ break;
+ }
+ }
+ }
+ sub_index++;
+ }
+ index++;
+ }
+ return errors;
+}
+#endif
+
+/// \brief get the version
+std::string PluginsManager::getPluginVersion(const std::string &pluginName) const
+{
+ #ifdef ULTRACOPIER_MODE_SUPERCOPIER
+ if(pluginName=="supercopier")
+ return ULTRACOPIER_VERSION;
+ #else
+ if(pluginName=="ultracopier")
+ return ULTRACOPIER_VERSION;
+ #endif
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ unsigned int index=0;
+ while(index<pluginsList.size())
+ {
+ std::string version,internalName;
+ unsigned int sub_index=0;
+ while(sub_index<pluginsList.at(index).informations.size())
+ {
+ if(pluginsList.at(index).informations.at(sub_index).size()==2 && pluginsList.at(index).informations.at(sub_index).at(0)=="version")
+ version=pluginsList.at(index).informations.at(sub_index).at(1);
+ if(pluginsList.at(index).informations.at(sub_index).size()==2 && pluginsList.at(index).informations.at(sub_index).at(0)=="internalName")
+ internalName=pluginsList.at(index).informations.at(sub_index).at(1);
+ sub_index++;
+ }
+ if(internalName==pluginName)
+ return version;
+ index++;
+ }
+ return "";
+}
+
+/// \brief To compare version, \return true is case of error
+bool PluginsManager::compareVersion(const std::string &versionA,const std::string &sign,const std::string &versionB)
+{
+ std::vector<std::string> versionANumber=stringsplit(versionA,'.');
+ std::vector<std::string> versionBNumber=stringsplit(versionB,'.');
+ unsigned int index=0;
+ unsigned int defaultReturnValue=true;
+ if(sign=="<")
+ defaultReturnValue=false;
+ if(sign==">")
+ defaultReturnValue=false;
+ bool ok;
+ while(index<versionANumber.size() && index<versionBNumber.size())
+ {
+ unsigned int reaNumberA=stringtouint8(versionANumber.at(index),&ok);
+ if(!ok)
+ return true;
+ unsigned int reaNumberB=stringtouint8(versionBNumber.at(index),&ok);
+ if(!ok)
+ return true;
+ if(sign=="=" && reaNumberA!=reaNumberB)
+ return false;
+ if(sign=="<")
+ {
+ if(reaNumberA>reaNumberB)
+ return false;
+ if(reaNumberA<reaNumberB)
+ return true;
+ }
+ if(sign==">")
+ {
+ if(reaNumberA<reaNumberB)
+ return false;
+ if(reaNumberA>reaNumberB)
+ return true;
+ }
+ if(sign=="<=")
+ {
+ if(reaNumberA>reaNumberB)
+ return false;
+ if(reaNumberA<reaNumberB)
+ return true;
+ }
+ if(sign==">=")
+ {
+ if(reaNumberA<reaNumberB)
+ return false;
+ if(reaNumberA>reaNumberB)
+ return true;
+ }
+ index++;
+ }
+ return defaultReturnValue;
+}
+
+std::vector<PluginsAvailable> PluginsManager::getPluginsByCategory(const PluginType &category) const
+{
+ if(pluginsListIndexed.find(category)==pluginsListIndexed.cend())
+ return std::vector<PluginsAvailable>();
+ return pluginsListIndexed.at(category);
+}
+
+std::vector<PluginsAvailable> PluginsManager::getPlugins(bool withError) const
+{
+ std::vector<PluginsAvailable> list;
+ unsigned int index=0;
+ while(index<pluginsList.size())
+ {
+ if(withError || pluginsList.at(index).errorString.empty())
+ list.push_back(pluginsList.at(index));
+ index++;
+ }
+ return list;
+}
+
+/// \brief show the information
+void PluginsManager::showInformation(const std::string &path)
+{
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ unsigned int index=0;
+ while(index<pluginsList.size())
+ {
+ if(pluginsList.at(index).path==path)
+ {
+ if(pluginInformation==NULL)
+ {
+ pluginInformation=new PluginInformation();
+ connect(this, &PluginsManager::newLanguageLoaded, pluginInformation, &PluginInformation::retranslateInformation,Qt::QueuedConnection);
+ }
+ pluginInformation->setLanguage(mainShortName);
+ pluginInformation->setPlugin(pluginsList.at(index));
+ pluginInformation->show();
+ return;
+ }
+ index++;
+ }
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"item not selected");
+}
+
+void PluginsManager::showInformationDoubleClick()
+{
+// showInformation(false);
+}
+
+#ifdef ULTRACOPIER_PLUGIN_IMPORT_SUPPORT
+void PluginsManager::removeThePluginSelected(const std::string &path)
+{
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ unsigned int index=0;
+ while(index<pluginsList.size())
+ {
+ if(pluginsList.at(index).path==path)
+ {
+ QMessageBox::StandardButton reply;
+ // if(pluginsList.at(index).internalVersionAlternative.isEmpty())
+ reply = QMessageBox::question(NULL,tr("Remove %1").arg(QString::fromStdString(pluginsList.at(index).name)),tr("Are you sure about removing \"%1\" in version %2?").arg(QString::fromStdString(pluginsList.at(index).name)).arg(QString::fromStdString(pluginsList.at(index).version)),QMessageBox::Yes|QMessageBox::No,QMessageBox::No);
+ // else
+ // reply = QMessageBox::question(NULL,tr("Remove %1").arg(getTranslatedText(pluginsList.at(index),"name",mainShortName)),tr("Are you sure to wish remove \"%1\" in version %2 for the internal version %3?").arg(getTranslatedText(pluginsList.at(index),"name",mainShortName)).arg(pluginsList.at(index).version).arg(pluginsList.at(index).internalVersionAlternative),QMessageBox::Yes|QMessageBox::No,QMessageBox::No);
+ if(reply==QMessageBox::Yes)
+ {
+ emit onePluginWillBeUnloaded(pluginsList.at(index));
+ emit onePluginWillBeRemoved(pluginsList.at(index));
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"remove plugin at this path: "+pluginsList.at(index).path);
+ if(!ResourcesManager::removeFolder(pluginsList.at(index).path))
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"unable to remove the plugin");
+ QMessageBox::critical(NULL,tr("Error"),tr("Error while the removing plugin, please check the rights on the folder: \n%1").arg(QString::fromStdString(pluginsList.at(index).path)));
+ }
+ pluginsListIndexed.erase(pluginsListIndexed.find(pluginsList.at(index).category));
+ pluginsList.erase(pluginsList.begin()+index);
+ while(checkDependencies()!=0){};
+ }
+ return;
+ }
+ index++;
+ }
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"item not selected");
+}
+
+void PluginsManager::addPlugin(const ImportBackend &backend)
+{
+ if(backend==ImportBackend_File)
+ executeTheFileBackendLoader();
+}
+
+void PluginsManager::executeTheFileBackendLoader()
+{
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ if(importingPlugin)
+ {
+ QMessageBox::information(NULL,tr("Information"),tr("Previous import is in progress..."));
+ return;
+ }
+ std::string fileName = QFileDialog::getOpenFileName(NULL,tr("Open Ultracopier plugin"),QString(),tr("Ultracopier plugin (*.urc)")).toStdString();
+ if(fileName!="")
+ tryLoadPlugin(fileName);
+}
+
+void PluginsManager::tryLoadPlugin(const std::string &file)
+{
+ QFile temp(QString::fromStdString(file));
+ if(temp.open(QIODevice::ReadOnly))
+ {
+ importingPlugin=true;
+ lunchDecodeThread(temp.readAll());
+ temp.close();
+ }
+ else
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"unable to open the file: "+temp.errorString().toStdString());
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to open the plugin: %1").arg(temp.errorString()));
+ }
+}
+
+void PluginsManager::lunchDecodeThread(const QByteArray &data)
+{
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ decodeThread.setData(data);
+ decodeThread.start(QThread::LowestPriority);
+}
+
+void PluginsManager::decodingFinished()
+{
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ if(!decodeThread.errorFound())
+ {
+ QByteArray data=decodeThread.decodedData();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"data.size(): "+std::to_string(data.size()));
+ QTarDecode tarFile;
+ std::vector<char> cppdata;
+ cppdata.resize(data.size());
+ memcpy(cppdata.data(),data.data(),data.size());
+ if(!tarFile.decodeData(cppdata))
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"tarFile.errorString(): "+tarFile.errorString());
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to load the plugin content, please check it: %1").arg(QString::fromStdString(tarFile.errorString())));
+ }
+ else
+ {
+ std::vector<std::string> fileList = tarFile.getFileList();
+ std::vector<std::vector<char> > dataList = tarFile.getDataList();
+ if(fileList.size()>1)
+ {
+ std::string basePluginArchive="";
+ /* block use less for tar?
+ if(fileList.at(0).contains(QRegularExpression("[\\/]")))
+ {
+ bool folderFoundEveryWhere=true;
+ basePluginArchive=fileList.at(0);
+ basePluginArchive=std::regex_replace(basePluginArchive, std::regex("[\\/].*$"), "");
+ for (int i = 0; i < list.size(); ++i)
+ {
+ if(!stringStartWith(fileList.at(i),basePluginArchive))
+ {
+ folderFoundEveryWhere=false;
+ break;
+ }
+ }
+ if(folderFoundEveryWhere)
+ {
+ for (int i = 0; i < fileList.size(); ++i)
+ fileList[i].substr(basePluginArchive.size());
+ }
+ else
+ basePluginArchive="";
+ }*/
+ PluginsAvailable tempPlugin;
+ std::string categoryFinal="";
+ for (unsigned int i = 0; i < fileList.size(); ++i)
+ if(fileList.at(i)=="informations.xml")
+ {
+ loadPluginXml(&tempPlugin,QByteArray(dataList.at(i).data(),static_cast<int>(dataList.at(i).size())));
+ break;
+ }
+ if(tempPlugin.errorString=="")
+ {
+ categoryFinal=categoryToString(tempPlugin.category);
+ if(categoryFinal!="")
+ {
+ std::string writablePath=ResourcesManager::resourcesManager->getWritablePath();
+ if(writablePath!="")
+ {
+ QDir dir;
+ std::string finalPluginPath=writablePath+categoryFinal+FacilityEngine::separator()+tempPlugin.name+FacilityEngine::separator();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"writablePath: \""+writablePath+"\"");
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"basePluginArchive: \""+basePluginArchive+"\"");
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"categoryFinal: \""+categoryFinal+"\"");
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"finalPluginPath: \""+finalPluginPath+"\"");
+ if(!dir.exists(QString::fromStdString(finalPluginPath)))
+ {
+ bool errorFound=false;
+ for (unsigned int i = 0; i < fileList.size(); ++i)
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"file "+std::to_string(i)+": "+finalPluginPath+fileList.at(i));
+ std::string fileListEntry=fileList[i];
+ fileListEntry=std::regex_replace(fileListEntry, std::regex("^(..?[\\/])+"), "");
+ QFile currentFile(QString::fromStdString(finalPluginPath+fileListEntry));
+ QFileInfo info(currentFile);
+ if(!dir.exists(info.absolutePath()))
+ if(!dir.mkpath(info.absolutePath()))
+ {
+ ResourcesManager::resourcesManager->disableWritablePath();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"Unable to make the path: "+info.absolutePath().toStdString());
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to create a folder to install the plugin:\n%1").arg(info.absolutePath()));
+ errorFound=true;
+ break;
+ }
+ if(currentFile.open(QIODevice::ReadWrite))
+ {
+ currentFile.write(QByteArray(dataList.at(i).data(),static_cast<int>(dataList.at(i).size())));
+ currentFile.close();
+ }
+ else
+ {
+ ResourcesManager::resourcesManager->disableWritablePath();
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"Unable to make the file: "+info.absolutePath().toStdString()+", error:"+currentFile.errorString().toStdString());
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to create a file to install the plugin:\n%1\nsince:%2").arg(info.absolutePath()).arg(currentFile.errorString()));
+ errorFound=true;
+ break;
+ }
+ }
+ if(!errorFound)
+ {
+ if(loadPluginInformation(finalPluginPath))
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"push the new plugin into the real list");
+ while(checkDependencies()!=0){};
+ emit needLangToRefreshPluginList();
+ emit manuallyAdded(tempPlugin);
+ }
+ }
+ }
+ else
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"Folder with same name is present, skip the plugin installation: "+finalPluginPath);
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Folder with same name is present, skip the plugin installation:\n%1").arg(QString::fromStdString(finalPluginPath)));
+ }
+ }
+ else
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"Have not writable path, then how add you plugin?");
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to load the plugin content, please check it"));
+ }
+ }
+ else
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"category into informations.xml not found!");
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to load the plugin content, please check it"));
+ }
+ }
+ else
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Error in the xml: "+tempPlugin.errorString);
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to load the plugin content, please check it: %1").arg(QString::fromStdString(tempPlugin.errorString)));
+ }
+ }
+ else
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"No file found into the plugin");
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to load the plugin content, please check it"));
+ }
+ }
+ }
+ else
+ {
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"decodeThread.errorFound(), error: "+decodeThread.errorString().toStdString());
+ QMessageBox::critical(NULL,tr("Plugin loader"),tr("Unable to load the plugin content, please check it: %1").arg(decodeThread.errorString()));
+ }
+ importingPlugin=false;
+}
+#endif
+
+#ifndef ULTRACOPIER_PLUGIN_ALL_IN_ONE
+void PluginsManager::newAuthPath(const std::string &path)
+{
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start");
+ unsigned int index=0;
+ while(index<pluginsList.size())
+ {
+ if(pluginsList.at(index).path==path)
+ {
+ pluginsList[index].isAuth=true;
+ return;
+ }
+ index++;
+ }
+ ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"plugin not located");
+}
+#endif
+
+/// \brief transfor short plugin name into file name
+std::string PluginsManager::getResolvedPluginName(const std::string &name)
+{
+ #if defined(Q_OS_LINUX) || defined(Q_OS_HURD)
+ return "lib"+name+".so";
+ #elif defined(Q_OS_MAC)
+ #if defined(QT_DEBUG)
+ return "lib"+name+"_debug.dylib";
+ #else
+ return "lib"+name+".dylib";
+ #endif
+ #elif defined(Q_OS_WIN32)
+ #if defined(QT_DEBUG)
+ return name+"d.dll";
+ #else
+ return name+".dll";
+ #endif
+ #else
+ #error "Platform not supported"
+ #endif
+}
+
+bool operator==(PluginsAvailable pluginA,PluginsAvailable pluginB)
+{
+ return PluginsManager::isSamePlugin(pluginA,pluginB);
+}