mirror of https://github.com/JAJames/Jupiter.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
8.1 KiB
332 lines
8.1 KiB
/**
|
|
* Copyright (C) 2014-2015 Jessica James.
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Written by Jessica James <jessica.aj@outlook.com>
|
|
*/
|
|
|
|
#include <cstring>
|
|
#include <cstdio>
|
|
|
|
#if defined _WIN32
|
|
#include <Windows.h>
|
|
#define DIR_CHR '\\'
|
|
#define DEFAULT_PLUGINS_DIRECTORY "Plugins\\"
|
|
#else // _WIN32
|
|
#include <dlfcn.h>
|
|
#define DIR_CHR '/'
|
|
#define DEFAULT_PLUGINS_DIRECTORY "Plugins/"
|
|
#endif // _WIN32
|
|
|
|
#include "Plugin.h"
|
|
#include "Functions.h"
|
|
#include "ArrayList.h"
|
|
#include "CString.h"
|
|
#include "String.h"
|
|
|
|
Jupiter::StringS pluginDir = DEFAULT_PLUGINS_DIRECTORY;
|
|
|
|
Jupiter::ArrayList<Jupiter::Plugin> _plugins;
|
|
Jupiter::ArrayList<Jupiter::Plugin> *Jupiter::plugins = &_plugins;
|
|
struct dlib;
|
|
Jupiter::ArrayList<dlib> _libList;
|
|
|
|
Jupiter::Plugin::~Plugin()
|
|
{
|
|
for (size_t i = 0; i != _plugins.size(); i++)
|
|
{
|
|
if (_plugins.get(i) == this)
|
|
{
|
|
_plugins.remove(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct dlib
|
|
{
|
|
Jupiter::Plugin *plugin = nullptr;
|
|
#if defined _WIN32
|
|
HMODULE lib = nullptr;
|
|
#else // _WIN32
|
|
void *lib = nullptr;
|
|
#endif // _WIN32
|
|
~dlib();
|
|
};
|
|
|
|
dlib::~dlib()
|
|
{
|
|
if (dlib::lib != nullptr)
|
|
{
|
|
#if defined _WIN32
|
|
FreeLibrary(dlib::lib);
|
|
#else // _WIN32
|
|
dlclose(dllib::lib);
|
|
#endif // _WIN32
|
|
}
|
|
}
|
|
|
|
void Jupiter::setPluginDirectory(const Jupiter::ReadableString &dir)
|
|
{
|
|
if (pluginDir.set(dir) != 0 && pluginDir.get(pluginDir.size() - 1) != DIR_CHR) pluginDir += DIR_CHR;
|
|
}
|
|
|
|
const Jupiter::ReadableString &Jupiter::getPluginDirectory()
|
|
{
|
|
return pluginDir;
|
|
}
|
|
|
|
#if defined _WIN32
|
|
#define MODULE_FILE_EXTENSION ".dll"
|
|
#else // _WIN32
|
|
#define MODULE_FILE_EXTENSION ".so"
|
|
#endif // _WIN32
|
|
|
|
Jupiter::Plugin *Jupiter::loadPlugin(const Jupiter::ReadableString &pluginName)
|
|
{
|
|
return Jupiter::loadPluginFile(Jupiter::CStringS::Format("%.*s%.*s" MODULE_FILE_EXTENSION, pluginDir.size(), pluginDir.ptr(), pluginName.size(), pluginName.ptr()).c_str());
|
|
}
|
|
|
|
Jupiter::Plugin *Jupiter::loadPluginFile(const char *file)
|
|
{
|
|
dlib *dPlug = new dlib();
|
|
|
|
// Load the library
|
|
#if defined _WIN32
|
|
dPlug->lib = LoadLibraryA(file);
|
|
#else // _WIN32
|
|
dPlug->lib = dlopen(file, RTLD_LAZY);
|
|
#endif // _WIN32
|
|
if (dPlug->lib == nullptr)
|
|
{
|
|
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (File failed to load)" ENDL, file);
|
|
goto fail;
|
|
}
|
|
|
|
{
|
|
// Get the "getPlugin" function
|
|
typedef Jupiter::Plugin *(*func_type)(void);
|
|
#if defined _WIN32
|
|
func_type func = (func_type)GetProcAddress(dPlug->lib, "getPlugin");
|
|
#else // _WIN32
|
|
func_type func = (func_type)dlsym(dPlug->lib, "getPlugin");
|
|
#endif // _WIN32
|
|
if (func == nullptr)
|
|
{
|
|
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Invalid plugin)" ENDL, file);
|
|
goto fail;
|
|
}
|
|
|
|
dPlug->plugin = func();
|
|
if (dPlug->plugin == nullptr)
|
|
{
|
|
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to initialize)" ENDL, file);
|
|
goto fail;
|
|
}
|
|
}
|
|
{
|
|
// Get and execute the "load" function if it exists
|
|
typedef bool(*func_type)(void);
|
|
#if defined _WIN32
|
|
func_type func = (func_type)GetProcAddress(dPlug->lib, "load");
|
|
#else // _WIN32
|
|
func_type func = (func_type)dlsym(dPlug->lib, "load");
|
|
#endif // _WIN32
|
|
if (func != nullptr && func() == false)
|
|
{
|
|
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to load)" ENDL, file);
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
_libList.add(dPlug);
|
|
_plugins.add(dPlug->plugin);
|
|
|
|
return dPlug->plugin;
|
|
|
|
fail:
|
|
delete dPlug;
|
|
return nullptr;
|
|
}
|
|
|
|
bool Jupiter::freePlugin(size_t index)
|
|
{
|
|
if (index < _plugins.size())
|
|
{
|
|
// Do not free() the plugin; plugin gets free'd by FreeLibrary().
|
|
_plugins.remove(index);
|
|
dlib *dPlug = _libList.remove(index);
|
|
|
|
typedef void (*func_type)(void);
|
|
#if defined _WIN32
|
|
func_type func = (func_type)GetProcAddress(dPlug->lib, "unload");
|
|
#else // _WIN32
|
|
func_type func = (func_type)dlsym(dPlug->lib, "unload");
|
|
#endif // _WIN32
|
|
if (func != nullptr) func();
|
|
|
|
delete dPlug;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Jupiter::freePlugin(Jupiter::Plugin *plugin)
|
|
{
|
|
if (plugin == nullptr) return false;
|
|
for (size_t i = 0; i != _plugins.size(); i++) if (_plugins.get(i) == plugin) return Jupiter::freePlugin(i);
|
|
return false;
|
|
}
|
|
|
|
bool Jupiter::freePlugin(const Jupiter::ReadableString &pluginName)
|
|
{
|
|
if (pluginName == nullptr) return false;
|
|
for (size_t i = 0; i != _plugins.size(); i++) if (pluginName.matchi(_plugins.get(i)->getName())) return Jupiter::freePlugin(i);
|
|
return false;
|
|
}
|
|
|
|
Jupiter::Plugin *Jupiter::getPlugin(size_t index)
|
|
{
|
|
if (index < _plugins.size()) return _plugins.get(index);
|
|
return nullptr;
|
|
}
|
|
|
|
Jupiter::Plugin *Jupiter::getPlugin(const Jupiter::ReadableString &pluginName)
|
|
{
|
|
Jupiter::Plugin *p;
|
|
for (size_t i = 0; i != _plugins.size(); i++)
|
|
{
|
|
p = _plugins.get(i);
|
|
if (pluginName.matchi(p->getName())) return p;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// Event Placeholders
|
|
|
|
int Jupiter::Plugin::think()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int Jupiter::Plugin::OnRehash()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool Jupiter::Plugin::OnBadRehash(bool removed)
|
|
{
|
|
Jupiter::Plugin::_shouldRemove = removed;
|
|
return false;
|
|
}
|
|
|
|
bool Jupiter::Plugin::shouldRemove()
|
|
{
|
|
return Jupiter::Plugin::_shouldRemove;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnConnect(Jupiter::IRC::Client *)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnDisconnect(Jupiter::IRC::Client *)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnReconnectAttempt(Jupiter::IRC::Client *, bool)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnRaw(Jupiter::IRC::Client *, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnNumeric(Jupiter::IRC::Client *, long int, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnError(Jupiter::IRC::Client *, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnChat(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnServerNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnCTCP(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnAction(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnInvite(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnJoin(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnPart(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnNick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnKick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnQuit(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnMode(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void Jupiter::Plugin::OnThink(Jupiter::IRC::Client *)
|
|
{
|
|
return;
|
|
}
|