4
0
mirror of https://github.com/QuasarApp/qca.git synced 2025-05-07 08:19:33 +00:00

upgraded plugin loading system

svn path=/trunk/kdesupport/qca/; revision=251433
This commit is contained in:
Justin Karneges 2003-09-16 03:03:40 +00:00
parent 5564ba5d92
commit 772c9ba704
4 changed files with 149 additions and 72 deletions

14
TODO

@ -1,17 +1,3 @@
* rename qcaopenssl to qca-ssl and qcacyrussasl to qca-sasl and move them
* more optimal plugin loading:
plugins should have versions and names
load on demand
ability to add classes as plugins
ability to set priorities to plugins by name and feature
read plugins from QApplication::libraryPaths() - $DIR/crypto
* openssl plugin:
fixmes and todos
rename SSL to TLS
clean TLSContext, and make sure it reports crypt errors
* dsa
* diffie-hellman
* entropy

@ -7,17 +7,8 @@
#include<qlibrary.h>
#include<qtimer.h>
#include<qhostaddress.h>
#include<qapplication.h>
#include"qcaprovider.h"
#include<stdio.h>
#include<stdlib.h>
#ifdef USE_OPENSSL
#include"qcaopenssl.h"
#endif
#ifdef USE_CYRUSSASL
#include"qcacyrussasl.h"
#endif
#if defined(Q_OS_WIN32)
#define PLUGIN_EXT "dll"
@ -27,11 +18,123 @@
#define PLUGIN_EXT "so"
#endif
#define QCA_PLUGIN_VERSION 1
using namespace QCA;
static QPtrList<QCAProvider> providerList;
class ProviderItem
{
public:
QCAProvider *p;
static ProviderItem *load(const QString &fname)
{
QLibrary *lib = new QLibrary(fname);
if(!lib->load()) {
delete lib;
return 0;
}
void *s = lib->resolve("createProvider");
if(!s) {
delete lib;
return 0;
}
QCAProvider *(*createProvider)() = (QCAProvider *(*)())s;
QCAProvider *p = createProvider();
if(!p) {
delete lib;
return 0;
}
ProviderItem *i = new ProviderItem(lib, p);
return i;
}
static ProviderItem *fromClass(QCAProvider *p)
{
ProviderItem *i = new ProviderItem(0, p);
return i;
}
~ProviderItem()
{
delete p;
delete lib;
}
void ensureInit()
{
if(init_done)
return;
init_done = true;
p->init();
}
private:
QLibrary *lib;
bool init_done;
ProviderItem(QLibrary *_lib, QCAProvider *_p)
{
lib = _lib;
p = _p;
init_done = false;
}
};
static QPtrList<ProviderItem> providerList;
static bool qca_init = false;
static void plugin_scan()
{
QStringList dirs = QApplication::libraryPaths();
for(QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) {
QDir libpath(*it);
QDir dir(libpath.filePath("crypto"));
if(!dir.exists())
continue;
QStringList list = dir.entryList();
for(QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) {
QFileInfo fi(dir.filePath(*it));
if(fi.isDir())
continue;
if(fi.extension() != PLUGIN_EXT)
continue;
//printf("f=[%s]\n", fi.filePath().latin1());
ProviderItem *i = ProviderItem::load(fi.filePath());
if(!i)
continue;
if(i->p->qcaVersion() != QCA_PLUGIN_VERSION) {
delete i;
continue;
}
providerList.append(i);
}
}
}
static void plugin_addClass(QCAProvider *p)
{
ProviderItem *i = ProviderItem::fromClass(p);
providerList.prepend(i);
}
static void plugin_unloadall()
{
providerList.clear();
}
static int plugin_caps()
{
int caps = 0;
QPtrListIterator<ProviderItem> it(providerList);
for(ProviderItem *i; (i = it.current()); ++it)
caps |= i->p->capabilities();
return caps;
}
QString QCA::arrayToHex(const QByteArray &a)
{
QString out;
@ -61,67 +164,50 @@ void QCA::init()
if(qca_init)
return;
qca_init = true;
providerList.clear();
#ifdef USE_OPENSSL
providerList.append(createProviderOpenSSL());
#endif
#ifdef USE_CYRUSSASL
providerList.append(createProviderCyrusSASL());
#endif
// load plugins
QDir dir("plugins");
QStringList list = dir.entryList();
for(QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) {
QFileInfo fi(dir.filePath(*it));
//printf("f=[%s]\n", fi.filePath().latin1());
if(fi.extension() != PLUGIN_EXT)
continue;
QLibrary *lib = new QLibrary(fi.filePath());
if(!lib->load()) {
delete lib;
//printf("can't load\n");
continue;
}
void *s = lib->resolve("createProvider");
if(!s) {
delete lib;
continue;
}
QCAProvider *(*createProvider)() = (QCAProvider *(*)())s;
QCAProvider *p = createProvider();
if(!p) {
delete lib;
continue;
}
providerList.append(p);
}
providerList.setAutoDelete(true);
}
bool QCA::isSupported(int capabilities)
{
init();
int caps = 0;
QPtrListIterator<QCAProvider> it(providerList);
for(QCAProvider *p; (p = it.current()); ++it)
caps |= p->capabilities();
int caps = plugin_caps();
if(caps & capabilities)
return true;
else
return false;
// ok, try scanning for new stuff
plugin_scan();
caps = plugin_caps();
if(caps & capabilities)
return true;
return false;
}
void QCA::insertProvider(QCAProvider *p)
{
plugin_addClass(p);
}
void QCA::unloadAllPlugins()
{
plugin_unloadall();
}
static void *getContext(int cap)
{
init();
QPtrListIterator<QCAProvider> it(providerList);
for(QCAProvider *p; (p = it.current()); ++it) {
if(p->capabilities() & cap)
return p->context(cap);
// this call will also trip a scan for new plugins if needed
if(!QCA::isSupported(cap))
return 0;
QPtrListIterator<ProviderItem> it(providerList);
for(ProviderItem *i; (i = it.current()); ++it) {
if(i->p->capabilities() & cap) {
i->ensureInit();
return i->p->context(cap);
}
}
return 0;
}

@ -11,6 +11,7 @@
class QHostAddress;
class QStringList;
class QCAProvider;
class QCA_HashContext;
class QCA_CipherContext;
class QCA_CertContext;
@ -43,6 +44,8 @@ namespace QCA
void init();
bool isSupported(int capabilities);
void insertProvider(QCAProvider *);
void unloadAllPlugins();
QString arrayToHex(const QByteArray &);
QByteArray hexToArray(const QString &);

@ -20,6 +20,8 @@ public:
QCAProvider() {}
virtual ~QCAProvider() {}
virtual void init()=0;
virtual int qcaVersion() const=0;
virtual int capabilities() const=0;
virtual void *context(int cap)=0;
};