diff options
Diffstat (limited to 'src/modules/system')
-rw-r--r-- | src/modules/system/Makefile.am | 18 | ||||
-rw-r--r-- | src/modules/system/libkvisystem.cpp | 749 | ||||
-rw-r--r-- | src/modules/system/plugin.cpp | 427 | ||||
-rw-r--r-- | src/modules/system/plugin.h | 80 |
4 files changed, 1274 insertions, 0 deletions
diff --git a/src/modules/system/Makefile.am b/src/modules/system/Makefile.am new file mode 100644 index 00000000..69302d13 --- /dev/null +++ b/src/modules/system/Makefile.am @@ -0,0 +1,18 @@ +############################################################################### +# KVirc IRC client Makesystem - 10.03.2000 Szymon Stefanek <[email protected]> +############################################################################### + +AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \ +$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\" + +pluglib_LTLIBRARIES = libkvisystem.la + +libkvisystem_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS) + +libkvisystem_la_SOURCES = libkvisystem.cpp plugin.cpp +libkvisystem_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la + +noinst_HEADERS = plugin.h + +%.moc: %.h + $(SS_QT_MOC) $< -o $@ diff --git a/src/modules/system/libkvisystem.cpp b/src/modules/system/libkvisystem.cpp new file mode 100644 index 00000000..54ada405 --- /dev/null +++ b/src/modules/system/libkvisystem.cpp @@ -0,0 +1,749 @@ +//============================================================================= +// +// File : libkvisystem.cpp +// Creation date : Fri Nov 16 03:50:12 2001 GMT by Szymon Stefanek +// +// This system is part of the KVirc irc client distribution +// Copyright (C) 2001-2005 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//============================================================================= + +#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" +#include "kvi_app.h" +#include "kvi_env.h" +#include "kvi_osinfo.h" +#include "kvi_qcstring.h" + +#include <qclipboard.h> + +#ifndef COMPILE_ON_WINDOWS + #include <sys/utsname.h> + #include <stdlib.h> + #include <unistd.h> +#endif + +#ifdef COMPILE_KDE_SUPPORT + #include <dcopclient.h> +#endif + +#include "kvi_modulemanager.h" + +#include "plugin.h" + +KviPluginManager * g_pPluginManager; + +/* + @doc: system.ostype + @type: + function + @title: + $system.ostype + @short: + Returns the type of the operating system + @syntax: + <string> $system.ostype() + @description: + Returns the current type of operating system: unix,macosx or windows.[br] +*/ + +static bool system_kvs_fnc_ostype(KviKvsModuleFunctionCall * c) +{ + c->returnValue()->setString(KviOsInfo::type()); + return true; +} +/* + @doc: system.osname + @type: + function + @title: + $system.osname + @short: + Returns the name of the operating system + @syntax: + <string> $system.osname() + @description: + Returns the name of the operating system. On UNIX like machines + this is the field sysname of the utsname structure returned by + the uname() syscall. +*/ + +static bool system_kvs_fnc_osname(KviKvsModuleFunctionCall *c) +{ + c->returnValue()->setString(KviOsInfo::name()); + return true; +} + + +/* + @doc: system.osversion + @type: + function + @title: + $system.osversion + @short: + Returns the version of the operating system + @syntax: + <string> $system.osversion() + @description: + Returns the version of the operating system.[br] +*/ + +static bool system_kvs_fnc_osversion(KviKvsModuleFunctionCall *c) +{ + // no params to process + c->returnValue()->setString(KviOsInfo::version()); + return true; +} + +/* + @doc: system.osrelease + @type: + function + @title: + $system.osrelease + @short: + Returns the release of the operating system + @syntax: + <string> $system.osrelease() + @description: + Returns the release of the operating system.[br] +*/ + +static bool system_kvs_fnc_osrelease(KviKvsModuleFunctionCall *c) +{ + // no params to process + c->returnValue()->setString(KviOsInfo::release()); + return true; +} + +/* + @doc: system.osmachine + @type: + function + @title: + $system.osmachine + @short: + Returns the machine of the operating system + @syntax: + <string> $system.osmachine() + @description: + Returns the machine of the operating system.[br] +*/ + +static bool system_kvs_fnc_osmachine(KviKvsModuleFunctionCall *c) +{ + // no params to process + c->returnValue()->setString(KviOsInfo::machine()); + return true; +} + +/* + @doc: system.osnodename + @type: + function + @title: + $system.osnodename + @short: + Returns the nodename of the operating system + @syntax: + <string> $system.osnodename() + @description: + Returns the nodename of the operating system.[br] +*/ + +static bool system_kvs_fnc_osnodename(KviKvsModuleFunctionCall *c) +{ + // no params to process + c->returnValue()->setString(KviOsInfo::nodename()); + return true; +} + +/* + @doc: system.getenv + @keyterms: + Enviroinement variables + @type: + function + @title: + $system.getenv + @short: + Returns the value of an enviroinement variable + @syntax: + <string> $system.getenv(<variable:string>) + @description: + Returns the value of the enviroinement <variable>.[br] +*/ + +static bool system_kvs_fnc_getenv(KviKvsModuleFunctionCall *c) +{ + QString szVariable; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("variable",KVS_PT_NONEMPTYSTRING,0,szVariable) + KVSM_PARAMETERS_END(c) + + KviQCString szVar = szVariable.local8Bit(); +#ifdef COMPILE_ON_WINDOWS + QString env = getenv(szVar.data()); + QString def = __tr2qs("No environment variable found, please don't use the %% in the request"); + c->returnValue()->setString(env.isEmpty() ? QString::fromLocal8Bit(env) : QString::fromLocal8Bit(def)); +#else + char * b = kvi_getenv(szVar.data()); + c->returnValue()->setString(b ? QString::fromLocal8Bit(b) : QString::null); +#endif + return true; +} + +/* + @doc: system.clipboard + @keyterms: + Clipboard management + @type: + function + @title: + $system.clipboard + @short: + Returns the value of the system clipboard + @syntax: + <string> $system.clipboard() + @description: + Returns the current value of the system clipboard. + Please note that there are systems that have the concept + of "selection" (most notably X11) which is NOT the same as the clipboard. + See [fnc]$system.selection[/fnc](). + @seealso: + [fnc]$system.selection[/fnc], + [cmd]system.setClipboard[/cmd], + [cmd]system.setSelection[/cmd] +*/ + +static bool system_kvs_fnc_clipboard(KviKvsModuleFunctionCall *c) +{ + c->returnValue()->setString(g_pApp->clipboard()->text(QClipboard::Clipboard)); + return true; +} + + +/* + @doc: system.setClipboard + @type: + command + @title: + system.setClipboard + @keyterms: + Clipboard management + @short: + Sets the current system clipboard contents + @syntax: + system.setClipboard <data:string> + @description: + Sets the system clipboard contents to the string <data>. + Please note that there are systems that have the concept + of "selection" (most notably X11) which is NOT the same as the clipboard. + See [fnc]$system.selection[/fnc](). + @seealso: + [fnc]$system.selection[/fnc], + [fnc]$system.clipboard[/fnc], + [cmd]system.setSelection[/cmd] +*/ + +static bool system_kvs_cmd_setClipboard(KviKvsModuleCommandCall * c) +{ + QString szValue; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("data",KVS_PT_STRING,KVS_PF_OPTIONAL,szValue) + KVSM_PARAMETERS_END(c) + g_pApp->clipboard()->setText(szValue,QClipboard::Clipboard); + return true; +} + +/* + @doc: system.setSelection + @type: + command + @title: + system.setSelection + @keyterms: + Clipboard management + @short: + Sets the current system selection contents + @syntax: + system.setSelection <data:string> + @description: + Sets the system selection contents to the string <data>. + Please note that this command will work only on systems that have the concept + of "selection" (most notably X11) which is NOT the same as the clipboard. + @seealso: + [fnc]$system.selection[/fnc], + [fnc]$system.clipboard[/fnc], + [cmd]system.setClipboard[/cmd] +*/ + +static bool system_kvs_cmd_setSelection(KviKvsModuleCommandCall * c) +{ + QString szValue; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("data",KVS_PT_STRING,KVS_PF_OPTIONAL,szValue) + KVSM_PARAMETERS_END(c) + g_pApp->clipboard()->setText(szValue,QClipboard::Selection); + return true; +} + +/* + @doc: system.selection + @keyterms: + Clipboard management + @type: + function + @title: + $system.selection + @short: + Returns the value of the system selection + @syntax: + <string> $system.selection() + @description: + Returns the current value of the system selection. + This function will work only on systems that have the concept + of "selection" (most notably X11) which is NOT the same as clipboard. + On other systems this function will always return an empty string. + See [fnc]$system.clipboard[/fnc](). + @seealso: + [fnc]$system.clipboard[/fnc], + [cmd]system.setClipboard[/cmd], + [cmd]system.setSelection[/cmd] +*/ + +static bool system_kvs_fnc_selection(KviKvsModuleFunctionCall *c) +{ + c->returnValue()->setString(g_pApp->clipboard()->text(QClipboard::Selection)); + return true; +} + + +/* + @doc: system.checkModule + @keyterms: + Module checking + @type: + function + @title: + $system.checkModule + @short: + Checks if a KVIrc module is loadable + @syntax: + <boolean> $system.checkModule(<module_name:string>) + @description: + Attempts to load the specified module and returns + $true if succesfull and $false otherwise. This can + be effectively used to test if a KVIrc exension module + is present on the system and can be loaded by the + KVIrc engine. +*/ + +static bool system_kvs_fnc_checkModule(KviKvsModuleFunctionCall *c) +{ + QString szModuleName; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("module_name",KVS_PT_STRING,0,szModuleName) + KVSM_PARAMETERS_END(c) + + c->returnValue()->setBoolean(g_pModuleManager->loadModule(szModuleName.utf8().data())); + return true; +} + + +/* + @doc: system.hostname + @keyterms: + System information + @type: + function + @title: + $system.hostname + @short: + Returns the hostname of the machine that KVIrc is running on + @syntax: + <string> $system.hostname() + @description: + Returns the hostname of the machine that KVIrc is running on.[br] +*/ + +static bool system_kvs_fnc_hostname(KviKvsModuleFunctionCall *c) +{ + // no params to process + c->returnValue()->setString(KviOsInfo::hostname()); + return true; +} + + +/* + @doc: system.dcop + @keyterms: + System information + @type: + function + @title: + $system.dcop + @short: + Performs a DCOP call + @syntax: + <variant> $system.dcop(<application:string>,<objectid:string>,<function:string>[,<parameter1:string>[,<parameter2:string>[,...]]]) + @description: + This function allows performing simple DCOP calls without executing + an external process. This feature is available ONLY when KDE support + is compiled in the executable: this means that this function is absolutely + non portable (don't use it in scripts that you're going to distribute). + <application> is the name of the application being called, <objectid> is the + identifier of the object called, <function> is the function to be executed + on the remote object and <parameter1>,<parameter2>,... is the list of + parameters to be passed. The <function> name must contain the + trailing parenthesis and parameter specification (see examples). + The parameters MUST be in the form "type=value" + where "type" is the C++ type of the parameter and value + is the string rappresentation of the parameter data. Currently + KVIrc supports only QString,KviQCString,bool,int and uint data types.[br] + The returned value is the string rappresentation of the returned + data if the return type is known, otherwise it is the name of the data type returned. + [br] + If the application name is prefixed with "?" then the call is performed in "remote test" + mode: no "remote" errors are printed and the function returns 1 if the call executed + succesfully and 0 if the call failed. This can be used with the very first + call to programmaticaly test if the remote application is running. + @examples: + [example] + echo $system.dcop("kdesktop","KBackgroundIface","currentWallpaper(int)","int=0") + echo $system.dcop("kdesktop","KScreensaverIface","lock()") + # we can also ignore the return value in several ways + %dummy = $system.dcop("kicker","kicker","showKMenu()") + $system.dcop("kdesktop","KScreensaverIface","save()") + $system.dcop("kicker","Panel","addBrowserButton(QString)","QString=/") + # runtime test if a call would work (i.e. , kicker is running at all, parameters are right etc...) + if($system.dcop("?kicker","kicker","showKMenu()"))echo "Can't make dcop calls to kicker!" + [/example] +*/ + +static bool system_kvs_fnc_dcop(KviKvsModuleFunctionCall *c) +{ + bool bTestMode = false; + + KviQCString szApp,szObj,szFun; + QStringList parms; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("application",KVS_PT_NONEMPTYCSTRING,0,szApp) + KVSM_PARAMETER("objectid",KVS_PT_NONEMPTYCSTRING,0,szObj) + KVSM_PARAMETER("function",KVS_PT_NONEMPTYCSTRING,0,szFun) + KVSM_PARAMETER("parameter_list",KVS_PT_STRINGLIST,KVS_PF_OPTIONAL,parms) + KVSM_PARAMETERS_END(c) + + if((szApp.data()) && (szApp.length() > 1)) + { + if(*(szApp.data()) == '?') + { + bTestMode = true; + szApp.remove(0,1); + } + } + +#ifdef COMPILE_KDE_SUPPORT + + QByteArray ba; + QDataStream ds(ba, IO_WriteOnly); + + for ( QStringList::Iterator it = parms.begin(); it != parms.end(); ++it ) + { + KviStr tmp = *it; + + if(tmp.isEmpty()) + { + c->warning(__tr2qs("Invalid DCOP parameter syntax")); + return false; + } + + KviStr szType = tmp.leftToFirst('=',false); + tmp.cutToFirst('=',true); + if(szType.isEmpty())szType = "int"; + bool bOk; + if(kvi_strEqualCI("int",szType.ptr()) || kvi_strEqualCI("long",szType.ptr())) + { + int iii = tmp.toInt(&bOk); + if(!bOk) + { + c->warning(__tr2qs("The specified parameter is not an integer")); + return false; + } + ds << iii; + } else if(kvi_strEqualCI("QString",szType.ptr())) + { + QString ddd = tmp.ptr(); + ds << ddd; + } else if(kvi_strEqualCI("KviQCString",szType.ptr())) + { + KviQCString qcs = tmp.ptr(); + ds << qcs; + } else if(kvi_strEqualCI("bool",szType.ptr())) + { + bool bbb = kvi_strEqualCI(tmp.ptr(),"true"); + ds << bbb; + } else if(kvi_strEqualCI("unsigned int",szType.ptr()) || kvi_strEqualCI("uint",szType.ptr()) || kvi_strEqualCI("Q_UINT32",szType.ptr())) + { + unsigned int uii = tmp.toUInt(&bOk); + if(!bOk) + { + c->warning(__tr2qs("The specified parameter is not an integer")); + return false; + } + ds << uii; + } else { + c->warning(__tr2qs("Unsupported DCOP parameter type %s"),tmp.ptr()); + return false; + } + } + + QByteArray rba; + KviQCString szRetType; + + bool bRet = g_pApp->dcopClient()->call(szApp,szObj,szFun,ba,szRetType,rba); + + if(!bRet) + { + if(!bTestMode) + c->warning(__tr2qs("DCOP call failed")); + c->returnValue()->setInteger(0); + } else { + if(bTestMode) + c->returnValue()->setInteger(1); + else { + QDataStream ret(rba, IO_ReadOnly); + if(szRetType == "bool") + { + bool bqw; + ret >> bqw; + c->returnValue()->setInteger(bqw ? 1 : 0); + } else if(szRetType == "QString") + { + QString szz; + ret >> szz; + c->returnValue()->setString(szz); + } else if(szRetType == "QCString") + { + KviQCString sss; + ret >> sss; + c->returnValue()->setString(sss.data()); + } else if((szRetType == "uint") || (szRetType == "unsigned int") || (szRetType == "Q_UINT32")) + { + unsigned int ui3; + ret >> ui3; + c->returnValue()->setInteger(ui3); + } else if((szRetType == "int") || (szRetType == "long")) + { + int iii; + ret >> iii; + c->returnValue()->setInteger(iii); + } else if(szRetType == "QCStringList") + { +#ifndef COMPILE_USE_QT4 + QCStringList csl; + ret >> csl; + KviKvsArray * arry = new KviKvsArray(); + int idx = 0; + for(QCStringList::Iterator iter = csl.begin();iter != csl.end();++iter) + { + arry->set(idx,new KviKvsVariant(QString(*iter))); + idx++; + } + c->returnValue()->setArray(arry); +#endif + } else if(szRetType == "QStringList") + { + QStringList csl; + ret >> csl; + KviKvsArray * arry = new KviKvsArray(); + int idx = 0; + for(QStringList::Iterator iter = csl.begin();iter != csl.end();++iter) + { + arry->set(idx,new KviKvsVariant(*iter)); + idx++; + } + c->returnValue()->setArray(arry); + } else { + c->returnValue()->setString(szRetType.data()); + } + } + } +#else + if(!bTestMode) + c->warning(__tr2qs("DCOP calls are available only when KDE support is compiled in")); + c->returnValue()->setInteger(0); +#endif + + return true; +} + + +/* + @doc: system.setenv + @type: + command + @title: + system.setenv + @keyterms: + Enviroinement variables + @short: + Sets an enviroinement variable + @syntax: + system.setenv <variable:string> [<value:string>] + @description: + Sets the enviroinement <variable> to the <value> string.[br] + If <value> is not given , the <variable> is unset.[br] + @seealso: + [fnc]$system.getenv[/fnc] +*/ + + +static bool system_kvs_cmd_setenv(KviKvsModuleCommandCall * c) +{ + QString szVariable,szValue; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("variable",KVS_PT_NONEMPTYSTRING,0,szVariable) + KVSM_PARAMETER("value",KVS_PT_STRING,KVS_PF_OPTIONAL,szValue) + KVSM_PARAMETERS_END(c) + + KviQCString szVar = szVariable.local8Bit(); + KviQCString szVal = szValue.local8Bit(); + + if(szVal.isEmpty())kvi_unsetenv(szVar.data()); + else + { +/*#ifdef COMPILE_ON_WINDOWS + QString Var,Val,VarAndVal; + Val = szVar.data(); + Var = szVal.data(); + VarAndVal = Var+"="+Val; + putenv(VarAndVal); +#else*/ // <-- this stuff is implicit in kvi_setenv: that's why we have the kvi_ version. + kvi_setenv(szVar.data(),szVal.data()); +/*#endif*/ + } + return true; +} + +/* + @doc: system.call + @keyterms: + call plugin + @type: + function + @title: + $system.call + @short: + Allows to call functions of a plugin + @syntax: + <string> $system.call(<plugin:string>, <function:string>[,<parameters:string>,...]) + @description: + This function allows you to call simple functions of "easyplugins" (dll/so) and + get the result of this function. The easyplugins have to be coded in a special way. + If you want to write your own easyplugins, have a look on the easyplugins documentation. + [br] + [br] + The function needs a minimum of 2 parameters. The others are optional and not limited.[br] + The first one is the complete name like "example.dll" or "example.so" + If you have a relative path or only the filename KVIrc looks for the easyplugins in the following dirs:[br] + In a subdir called "easyplugins" in the local and global KVIrc directory. + If you give an absolute path KVIrc will load it directly. + [br] + [br] + You are free to add more parameters, they will be given to the easyplugin.[br] + The easyplugin decides how much parameters you need in addition to the first 2. + [br] + [br] + [b]Warning: Only use easyplugins of known and trustable sources![/b] + @examples: + [example] + echo $system.call("my.dll","myfunction") + echo $system.call("my.dll","myfunction","parameter1","parameter2") + echo $system.call("c:/my.dll","myfunction") + echo $system.call("my.so","myfunction","parameter1") + [/example] +*/ + + +static bool system_kvs_fnc_plugin_call(KviKvsModuleFunctionCall *c) +{ + return g_pPluginManager->pluginCall(c); +} + +static bool system_module_init(KviModule * m) +{ + KVSM_REGISTER_FUNCTION(m,"ostype",system_kvs_fnc_ostype); + KVSM_REGISTER_FUNCTION(m,"osname",system_kvs_fnc_osname); + KVSM_REGISTER_FUNCTION(m,"osversion",system_kvs_fnc_osversion); + KVSM_REGISTER_FUNCTION(m,"osrelease",system_kvs_fnc_osrelease); + KVSM_REGISTER_FUNCTION(m,"osmachine",system_kvs_fnc_osmachine); + KVSM_REGISTER_FUNCTION(m,"osnodename",system_kvs_fnc_osnodename); + KVSM_REGISTER_FUNCTION(m,"getenv",system_kvs_fnc_getenv); + KVSM_REGISTER_FUNCTION(m,"hostname",system_kvs_fnc_hostname); + KVSM_REGISTER_FUNCTION(m,"dcop",system_kvs_fnc_dcop); + 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(); + delete g_pPluginManager; + return true; +} + +static bool system_module_can_unload(KviModule *m) +{ + if(!g_pPluginManager->checkUnload()) return false; + return true; +} + +KVIRC_MODULE( + "System", // module name + "1.0.0", // module version + "Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)" \ + " (C) 2005 Tonino Imbesi (grifisx at barmes dot org)"\ + " (C) 2005 Alessandro Carbone (noldor at barmes dot org)",// author & (C) + "System informations module", + system_module_init, + 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 00000000..b14b18c0 --- /dev/null +++ b/src/modules/system/plugin.cpp @@ -0,0 +1,427 @@ +//============================================================================= +// +// 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "kvi_fileutils.h" + +#include <qdir.h> +#include <qfileinfo.h> +/* + @doc: easyplugins + @type: + generic + @keyterms: + easyplugins + @title: + Easyplugins + @short: + Small plugins which can be called in scripts + @body: + If you want to know how to call easyplugins please have a look at: $system.call()[br] + This part of the documentation handles only the way how to write an easyplugin. An easyplugin is simply a dll/so. You can create one like you normally make such so/dll files. The important thing is that these so/dll-files export some of the following functions. + [br][br] + [b]Exported functions by easyplugin (C/C++-Examples):[/b][br] + [br][b]_free function[/b] [i] (needed)[/i][br] + This function is important! Since KVIrc can not free directly the memory of the dll, the plugins need the _free function so that the memory can be freed by the plugin to prevent memory-leaks.[br] + [example] + int _free(void * p)[br] + {[br] + // Always free the memory here![br] + free(p);[br] + return 0;[br] + }[br] + [/example] + + [br][b]_load function[/b] [i](optional)[/i][br] + After the plugin has be loaded, KVIrc will call the _load-function. Here you can prepare your plugin stuff. + [example] + int _load()[br] + {[br] + return 0;[br] + }[br] + [/example] + + [br][b]_unload function[/b] [i]((optional)[/i][br] + This function will be called before the plugins is unloaded. In this function you can clean up memory or other things. + After this call there is no guarantee that the plugin will be kept in memory.[br] + [example] + int _unload()[br] + {[br] + return 0;[br] + }[br] + [/example] + + [br][b]_canunload function[/b] [i](optional)[/i][br] + The _canunload-function will be called by KVIrc to check if it may unload the plugin. + If return value is true KVIrc will unload the plugin, false means he will try unloading it at the next check.[br] + Important: KVIrc will ignore this if unload of plugins will be forced! So you have to be sure that the _unload function of your plugins cleans up![br] + [example] + int _canunload()[br] + {[br] + return 0; [br] + }[br] + [/example] + + [br][b]user function[/b][br] + This is the general structure of a user function call.[br] + The important thing here is the handling of return values. To return a value to KVIrc you have to allocate memory and write the pointer to it into pBuffer. Have a look at the example for more details.[br] + [example] + int about(int argc, char * argv[], char ** pBuffer)[br] + {[br] + *pBuffer = (char*)malloc(1024);[br] + sprintf((char*)*pBuffer, "Hello World"); [br] + return 1;[br] + }[br] + [/example] +*/ + +KviPlugin::KviPlugin(kvi_library_t pLib, const QString& name) +{ + m_Plugin = pLib; + m_szName = name; +} + +KviPlugin::~KviPlugin() +{ +} + +KviPlugin* KviPlugin::load(const QString& szFileName) +{ + kvi_library_t pLibrary = kvi_library_open(szFileName.local8Bit()); + if (!pLibrary) + { + return 0; + } + + KviPlugin* pPlugin = new KviPlugin(pLibrary,KviFileUtils::extractFileName(szFileName)); + + plugin_load function_load; + + function_load = (plugin_unload)kvi_library_symbol(pLibrary,"_load"); + if (function_load) + { + //TODO: THREAD + function_load(); + } + return pPlugin; +} + +bool KviPlugin::pfree(char * pBuffer) +{ + plugin_free function_free; + + function_free = (plugin_free)kvi_library_symbol(m_Plugin,"_free"); + if (function_free) + { + //TODO: THREAD + if(pBuffer) function_free(pBuffer); + return true; + } + return false; +} + +bool KviPlugin::unload() +{ + plugin_unload function_unload; + + function_unload = (plugin_unload)kvi_library_symbol(m_Plugin,"_unload"); + if (function_unload) + { + //TODO: THREAD + function_unload(); + } + + if(m_Plugin) + { + kvi_library_close(m_Plugin); + } + + return true; +} + +bool KviPlugin::canunload() +{ + plugin_canunload function_canunload; + + function_canunload = (plugin_canunload)kvi_library_symbol(m_Plugin,"_canunload"); + if (function_canunload) + { + //TODO: THREAD + if(!function_canunload()) + { + return false; + } + } + return true; +} + +int KviPlugin::call(const QString& pszFunctionName, int argc, char * argv[], char ** pBuffer) +{ + int r; + plugin_function function_call; + function_call = (plugin_function)kvi_library_symbol(m_Plugin,pszFunctionName.local8Bit()); + if (!function_call) + { + return -1; + } else { + //TODO: THREAD + r = function_call(argc,argv,pBuffer); + } + if (r < 0) r = 0; // negative numbers are for error handling. + return r; +} + +QString KviPlugin::name() +{ + return m_szName; +} + +void KviPlugin::setName(const QString& Name) +{ + m_szName = Name; +} + + +KviPluginManager::KviPluginManager() +{ + m_pPluginDict = new KviPointerHashTable<QString,KviPlugin>(5,false); + m_pPluginDict->setAutoDelete(false); + + m_bCanUnload = true; +} + +KviPluginManager::~KviPluginManager() +{ + delete m_pPluginDict; +} + +bool KviPluginManager::pluginCall(KviKvsModuleFunctionCall *c) +{ + // /echo $system.call("traffic.dll",about) + QString szPluginPath; //contains full path and plugin name like "c:/plugin.dll" + QString szFunctionName; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("plugin_path",KVS_PT_NONEMPTYSTRING,0,szPluginPath) + KVSM_PARAMETER("function",KVS_PT_NONEMPTYSTRING,0,szFunctionName) + KVSM_PARAMETERS_END(c) + + //Check if there is such a plugin + if(!findPlugin(szPluginPath)) + { + c->error(__tr2qs("Plugin not found. Please check the plugin-name and path.")); + return true; + } + + //Load plugin or check it in cache + if(!loadPlugin(szPluginPath)) + { + c->error(__tr2qs("Error while loading plugin.")); + return true; + } + + //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); + 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.local8Bit()); + x += tmp.length(); + + *x = 0; + x++; + i++; + } + + } else { + //Avoid using unfilled variables + ppArgv = 0; + pArgvBuffer = 0; + iArgc = 0; + } + + //Preparing return buffer + char * returnBuffer; + KviPlugin * plugin; + + plugin = getPlugin(szPluginPath); + 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(QString::fromLocal8Bit(returnBuffer)); + } + + + //Clean up + if(pArgvBuffer) free(pArgvBuffer); + if(ppArgv) free(ppArgv); + if(returnBuffer) + { + if (!plugin->pfree(returnBuffer)) + { + c->warning(__tr2qs("The plugin has no function to free memory. This can result in Memory Leaks!")); + } + } + + + + return true; +} + +bool KviPluginManager::checkUnload() +{ + /* + Always called when system module should be unloaded + Checking here if all small "modules" can be unloaded + */ + KviPointerHashTableIterator<QString,KviPlugin> it(*m_pPluginDict); + + m_bCanUnload = true; + + while(it.current()) + { + if(it.current()->canunload()) + { + it.current()->unload(); + m_pPluginDict->remove(it.currentKey()); + } else { + m_pPluginDict++; + m_bCanUnload = false; + } + } + + return m_bCanUnload; +} + +void KviPluginManager::unloadAll() +{ + KviPointerHashTableIterator<QString,KviPlugin> it(*m_pPluginDict); + + while(it.current()) + { + it.current()->unload(); + m_pPluginDict->remove(it.currentKey()); + } +} + +bool KviPluginManager::findPlugin(QString& szPath) +{ + QString szFileName(KviFileUtils::extractFileName(szPath)); +// szFileName.detach(); + if(KviFileUtils::isAbsolutePath(szPath) && KviFileUtils::fileExists(szPath)) + { + // Ok, + return true; + } else { + //Plugin not found in direct way. Looking in kvirc local dir + g_pApp->getGlobalKvircDirectory(szPath,KviApp::EasyPlugins,szFileName); + + if(!KviFileUtils::fileExists(szPath)) + { + //Plugin not found in kvirc local dir. Looking in kvirc global dir + g_pApp->getLocalKvircDirectory(szPath,KviApp::EasyPlugins,szFileName); + + if(!KviFileUtils::fileExists(szPath)) + { + return false; + } + } + } + return true; +} + +bool KviPluginManager::isPluginLoaded(const QString& pSingleName) +{ + KviPlugin * p = m_pPluginDict->find(pSingleName); + if (!p) + return false; + else + return true; +} + +bool KviPluginManager::loadPlugin(const QString& szPluginPath) +{ + if(isPluginLoaded(szPluginPath)) + { + return getPlugin(szPluginPath)!=0; + } else { + KviPlugin * plugin = KviPlugin::load(szPluginPath); + if(plugin) + { + m_pPluginDict->insert(szPluginPath,plugin); + return true; + } + } + return false; +} + +KviPlugin * KviPluginManager::getPlugin(const QString& szPluginPath) +{ + KviPlugin * p = m_pPluginDict->find(szPluginPath); + 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 00000000..64b1723a --- /dev/null +++ b/src/modules/system/plugin.h @@ -0,0 +1,80 @@ +#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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//============================================================================= + +#include "kvi_module.h" +#include "kvi_pointerhashtable.h" + +typedef int (*plugin_function)(int argc, char* argv[], char ** buffer); +typedef int (*plugin_unload)(); +typedef int (*plugin_canunload)(); +typedef int (*plugin_load)(); +typedef int (*plugin_free)(char * pBuffer); + +class KviPlugin +{ +protected: + // You have to create plugin instance by calling KviPlugin::load() + KviPlugin(kvi_library_t pLib, const QString& name); +public: + ~KviPlugin(); +private: + // shared + // internal + kvi_library_t m_Plugin; + QString m_szName; +public: + static KviPlugin* load(const QString& szFileName); + bool pfree(char * pBuffer); + bool unload(); + bool canunload(); + int call(const QString& szFunctionName, int argc, char * argv[], char ** pBuffer); + QString name(); + void setName(const QString& szName); +protected: +}; + +class KviPluginManager +{ + public: + KviPluginManager(); + ~KviPluginManager(); + private: + // shared + bool m_bCanUnload; + // internal + KviPointerHashTable<QString,KviPlugin> * m_pPluginDict; + public: + bool pluginCall(KviKvsModuleFunctionCall *c); + bool checkUnload(); + void unloadAll(); + protected: + bool findPlugin(QString& szName); + bool isPluginLoaded(const QString& szFileNameOrPathToLoad); + bool loadPlugin(const QString& szPluginPath); + KviPlugin * getPlugin(const QString& szPluginPath); +}; + +#endif //_PLUGIN_H_
\ No newline at end of file |