aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/system
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/system')
-rw-r--r--src/modules/system/libkvisystem.cpp40
-rw-r--r--src/modules/system/plugin.cpp331
-rw-r--r--src/modules/system/plugin.h76
-rw-r--r--src/modules/system/system_vc05.vcproj17
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"