diff options
Diffstat (limited to 'src/modules/system')
| -rw-r--r-- | src/modules/system/libkvisystem.cpp | 40 | ||||
| -rw-r--r-- | src/modules/system/plugin.cpp | 331 | ||||
| -rw-r--r-- | src/modules/system/plugin.h | 76 | ||||
| -rw-r--r-- | src/modules/system/system_vc05.vcproj | 17 |
4 files changed, 463 insertions, 1 deletions
diff --git a/src/modules/system/libkvisystem.cpp b/src/modules/system/libkvisystem.cpp index 759f852e3..7c18e4064 100644 --- a/src/modules/system/libkvisystem.cpp +++ b/src/modules/system/libkvisystem.cpp @@ -25,6 +25,8 @@ #include "kvi_settings.h" #include "kvi_module.h" #include "kvi_string.h" +#include "kvi_library.h" +#include "kvi_thread.h" #include "kvi_locale.h" #include "kvi_qcstring.h" @@ -47,6 +49,10 @@ #include "kvi_modulemanager.h" +#include "plugin.h" + +KviPluginManager * g_pPluginManager; + /* @doc: system.ostype @type: @@ -646,6 +652,27 @@ static bool system_kvs_cmd_setenv(KviKvsModuleCommandCall * c) return true; } +/* + @doc: system.call + @keyterms: + call plugin + @type: + function + @title: + $system.call + @short: + Allows to call functions of a plugin + @syntax: + <string> $system.plugin(<plugin:string>, <function:string>[,<parameters:string>,...]) + @description: + To be completed... +*/ + + +static bool system_kvs_fnc_plugin_call(KviKvsModuleFunctionCall *c) +{ + return g_pPluginManager->PluginCall(c); +} static bool system_module_init(KviModule * m) { @@ -661,16 +688,27 @@ static bool system_module_init(KviModule * m) KVSM_REGISTER_FUNCTION(m,"clipboard",system_kvs_fnc_clipboard); KVSM_REGISTER_FUNCTION(m,"selection",system_kvs_fnc_selection); KVSM_REGISTER_FUNCTION(m,"checkModule",system_kvs_fnc_checkModule); + KVSM_REGISTER_FUNCTION(m,"call",system_kvs_fnc_plugin_call); KVSM_REGISTER_SIMPLE_COMMAND(m,"setenv",system_kvs_cmd_setenv); KVSM_REGISTER_SIMPLE_COMMAND(m,"setClipboard",system_kvs_cmd_setClipboard); KVSM_REGISTER_SIMPLE_COMMAND(m,"setSelection",system_kvs_cmd_setSelection); + g_pPluginManager = new(KviPluginManager); + return true; } static bool system_module_cleanup(KviModule *m) { + g_pPluginManager->UnloadAll(true); + delete g_pPluginManager; + return true; +} + +static bool system_module_can_unload(KviModule *m) +{ + if(!g_pPluginManager->CheckUnload()) return false; return true; } @@ -682,7 +720,7 @@ KVIRC_MODULE( " (C) 2005 Alessandro Carbone (noldor at barmes dot org)",// author & (C) "System informations module", system_module_init, - 0, + system_module_can_unload, 0, system_module_cleanup ) diff --git a/src/modules/system/plugin.cpp b/src/modules/system/plugin.cpp new file mode 100644 index 000000000..1314c6127 --- /dev/null +++ b/src/modules/system/plugin.cpp @@ -0,0 +1,331 @@ +//============================================================================= +// +// File : plugin.cpp +// Creation date : Wed Apr 11 04 2007 00:54:00 GMT+1 by TheXception +// +// This file is part of the KVirc irc client distribution +// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot net) +// +// This program is FREE software. You can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your opinion) any later version. +// +// This program is distributed in the HOPE that it will be USEFUL, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, write to the Free Software Foundation, +// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +//============================================================================= + +#include "plugin.h" + +#include "kvi_module.h" +#include "kvi_string.h" +#include "kvi_library.h" +#include "kvi_thread.h" +#include "kvi_locale.h" +#include "kvi_app.h" + +#include <qdir.h> +#include <qfileinfo.h> + +KviPlugin::KviPlugin() +{ +} + +KviPlugin::~KviPlugin() +{ +} + +bool KviPlugin::load(QString * pszPluginName) +{ + m_Plugin = kvi_library_open(pszPluginName->ascii()); + if (!m_Plugin) + { + return false; + } + + plugin_load function_load; + + function_load = (plugin_unload)kvi_library_symbol(m_Plugin,"_load"); + if (function_load) + { + // ADD: THREAD + function_load(); + } + return true; +} + +bool KviPlugin::unload(bool forced) +{ + plugin_unload function_unload; + + function_unload = (plugin_unload)kvi_library_symbol(m_Plugin,"_unload"); + if (function_unload) + { + // ADD: THREAD + if(!function_unload()) + { + if(!forced) return false; + } + } + + if(m_Plugin) + { + kvi_library_close(m_Plugin); + } + + return true; +} + +int KviPlugin::call(QString * pszFunctionName, int argc, char * argv[], char ** pBuffer) +{ + int r; + plugin_function function_call; + function_call = (plugin_function)kvi_library_symbol(m_Plugin,pszFunctionName->ascii()); + if (!function_call) + { + return -1; + } else { + // ADD: THREAD + r = function_call(argc,argv,pBuffer); + } + if (r < 0) r = 0; // negative numbers are for error handling. + return r; +} + +KviStr KviPlugin::name() +{ + return m_szName; +} + +void KviPlugin::setName(QString * Name) +{ + m_szName = Name->ascii(); +} + + +KviPluginManager::KviPluginManager() +{ + m_pPluginDict = new KviAsciiDict<KviPlugin>(17,false); + m_pPluginDict->setAutoDelete(false); + + m_bCanUnload = true; +} + +KviPluginManager::~KviPluginManager() +{ + delete m_pPluginDict; +} + +bool KviPluginManager::PluginCall(KviKvsModuleFunctionCall *c) +{ + QString szPluginName; //contains full path and plugin name like "c:/plugin.dll" + QString szSinglePluginName; // contains only the name of the plugin like "plugin.dll" + QString szFunctionName; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("plugin",KVS_PT_NONEMPTYSTRING,0,szPluginName) + KVSM_PARAMETER("function",KVS_PT_NONEMPTYSTRING,0,szFunctionName) + KVSM_PARAMETERS_END(c) + + //Check if there is such a plugin + if(!FindPlugin(&szPluginName, &szSinglePluginName)) + { + c->error(__tr2qs("Plugin not found. Please check the plugin-name and path.")); + return true; + } + + // Check if plugin is already loaded + if(!PluginIsLoaded(&szSinglePluginName)) + { + c->warning("Plugin not loaded yet"); //REMOVE + //If not loaded try to load now + if(!LoadPlugin(&szPluginName,&szSinglePluginName)) + { + c->error(__tr2qs("Error while loading plugin.")); + return true; + } + } else c->warning("Plugin already loaded"); //REMOVE + + c->warning(szPluginName); //REMOVE + + //Parsing more Parameters + int iArgc = 0; + char ** ppArgv; + char * pArgvBuffer; + + //Preparing argv buffer + if(c->parameterCount() > 2) + { + iArgc = c->parameterCount() - 2; + } + + + + if (iArgc > 0) + { + int i = 2; + QString tmp; + int iSize = 0; + + //Calculate buffer size + while (i < (iArgc + 2) ) + { + c->params()->at(i)->asString(tmp); + c->warning(tmp); + iSize += tmp.length()+1; //+1 for the \0 characters + i++; + } + + //Allocate buffer + ppArgv = (char**)malloc(iArgc*sizeof(char*)); + pArgvBuffer = (char*)malloc(iSize); + + i = 2; + char * x = 0; + x = pArgvBuffer; + while (i < (iArgc + 2) ) + { + ppArgv[i-2] = x; + c->params()->at(i)->asString(tmp); + strcpy(x,tmp.ascii()); + x += tmp.length(); + + *x = 0; + x++; + i++; + } + + } else { + //Avoid using unfilled variables + ppArgv = (char**)malloc(0); + pArgvBuffer = (char*)malloc(0); + } + + //Preparing return buffer + char * returnBuffer; + + KviPlugin * plugin; + + plugin = GetPlugin(&szSinglePluginName); + int r = plugin->call(&szFunctionName,iArgc,ppArgv,&returnBuffer); + + if(r == -1) + { + c->error(__tr2qs("This plugin does not export the desired function.")); + return true; + } + if (r > 0) + { + c->returnValue()->setString(returnBuffer); + } + + //Clean up + free(pArgvBuffer); + free(ppArgv); + free(returnBuffer); + return true; +} + +bool KviPluginManager::CheckUnload() +{ + /* + Always called when system module should be unloaded + Checking here if all small "modules" can be unloaded + */ + KviAsciiDictIterator<KviPlugin> it(*m_pPluginDict); + + m_bCanUnload = true; + + while(it.current()) + { + if(it.current()->unload(false)) + { + m_pPluginDict->remove(it.current()->name()); + } else { + m_bCanUnload = false; + } + } + + return m_bCanUnload; +} + +void KviPluginManager::UnloadAll(bool forced) +{ + KviAsciiDictIterator<KviPlugin> it(*m_pPluginDict); + + while(it.current()) + { + it.current()->unload(true); + m_pPluginDict->remove(it.current()->name()); + } +} + +bool KviPluginManager::FindPlugin(QString * pName, QString * pSingleName) +{ + QDir d; + QFileInfo fi; + QString szPath; + + //Trying to find the plugin directly + d.setPath(*pName); + d.convertToAbs(); // To be sure that path is completly absolute! + + fi.setFile(d.path()); + if(!fi.exists()) + { + //Plugin not found in direct way. Looking in kvirc local dir + g_pApp->getGlobalKvircDirectory(szPath,KviApp::None,"easyplugins/"+*pName); + + d.setPath(szPath); + d.convertToAbs(); // To be sure that path is completly absolute! + + fi.setFile(d.path()); + if(!fi.exists()) + { + //Plugin not found in kvirc local dir. Looking in kvirc global dir + g_pApp->getLocalKvircDirectory(szPath,KviApp::None,"easyplugins/"+*pName); + + d.setPath(szPath); + d.convertToAbs(); // To be sure that path is completly absolute! + + fi.setFile(d.path()); + if(!fi.exists()) + { + return false; + } + } + } + + *pName = d.path(); + *pSingleName = fi.fileName(); + + return true; +} + +bool KviPluginManager::PluginIsLoaded(QString * pSingleName) +{ + KviPlugin * p = m_pPluginDict->find(pSingleName->ascii()); + if (!p) return false; else return true; +} + +bool KviPluginManager::LoadPlugin(QString * pName, QString * pSingleName) +{ + KviPlugin * plugin = new KviPlugin(); + if(!plugin->load(pName)) return false; + plugin->setName(pSingleName); + m_pPluginDict->insert(pSingleName->ascii(),plugin); + return true; +} + +KviPlugin * KviPluginManager::GetPlugin(QString * pSingleName) +{ + KviPlugin * p = m_pPluginDict->find(pSingleName->ascii()); + return p; +}
\ No newline at end of file diff --git a/src/modules/system/plugin.h b/src/modules/system/plugin.h new file mode 100644 index 000000000..c64a0f2d0 --- /dev/null +++ b/src/modules/system/plugin.h @@ -0,0 +1,76 @@ +#ifndef _PLUGIN_H_ +#define _PLUGIN_H_ +//============================================================================= +// +// File : plugin.h +// Creation date : Wed Apr 11 04 2007 00:54:00 GMT+1 by TheXception +// +// This file is part of the KVirc irc client distribution +// Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot net) +// +// This program is FREE software. You can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your opinion) any later version. +// +// This program is distributed in the HOPE that it will be USEFUL, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, write to the Free Software Foundation, +// Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +//============================================================================= + +#include "kvi_module.h" +#include "kvi_asciidict.h" + +#define MAX_RETURN_BUFFER 512 + +typedef int (*plugin_function)(int argc, char* argv[], char ** buffer); +typedef int (*plugin_unload)(); +typedef int (*plugin_load)(); + +class KviPlugin +{ + public: + KviPlugin(); + ~KviPlugin(); + private: + // shared + // internal + KviStr m_szName; + kvi_library_t m_Plugin; + public: + bool load(QString * pszPluginName); + bool unload(bool forced); + int call(QString * pszFunctionName, int argc, char * argv[], char ** pBuffer); + KviStr name(); + void setName(QString * Name); + protected: +}; + +class KviPluginManager +{ + public: + KviPluginManager(); + ~KviPluginManager(); + private: + // shared + bool m_bCanUnload; + // internal + KviAsciiDict<KviPlugin> * m_pPluginDict; + public: + bool PluginCall(KviKvsModuleFunctionCall *c); + bool CheckUnload(); + void UnloadAll(bool forced); + protected: + bool FindPlugin(QString * pName, QString * pSingleName); + bool PluginIsLoaded(QString * pSingleName); + bool LoadPlugin(QString * pName, QString * pSingleName); + KviPlugin * GetPlugin(QString * pSingleName); +}; + +#endif //_PLUGIN_H_
\ No newline at end of file diff --git a/src/modules/system/system_vc05.vcproj b/src/modules/system/system_vc05.vcproj index b1f590de9..da4af35e9 100644 --- a/src/modules/system/system_vc05.vcproj +++ b/src/modules/system/system_vc05.vcproj @@ -206,12 +206,29 @@ RelativePath=".\libkvisystem.cpp"
>
</File>
+ <File
+ RelativePath=".\plugin.cpp"
+ >
+ </File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
+ <File
+ RelativePath=".\plugin.h"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine=""
+ Outputs=""
+ />
+ </FileConfiguration>
+ </File>
</Filter>
<Filter
Name="Resource Files"
|
