diff options
Diffstat (limited to 'PluginsManager.cpp')
-rw-r--r-- | PluginsManager.cpp | 932 |
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); +} |