$Id: plugins.txt,v 1.8 2003/05/11 17:21:57 aquamaniac Exp $
This file describes how to add a Medium-Plugin to OpenHBCI.
What Is A Medium Plugin ?
=========================
A medium is something used to store the user's cryptographic keys.
They can be stored in a key file with some file format, or on a
chipcard, or on whatever type of medium you want to implement.
A medium plugin is a mechanism which provides support for a medium.
E.g., the plugin "DDVCard" provides support for DDV chipcards, so with
this plugin installed you are able to use such a card.
A plugin is either loaded on demand at run-time or statically linked into
OpenHBCI.
Rules For Creating a Medium Plugin
==================================
A plugin must follow these rules in order to be useable with OpenHBCI.
Medium Type String
------------------
A plugin for a specifc medium is identified by a unique medium type
string, e.g. "DDVCard", "RSACard", or "RDHFile". This string is the
identification by which an application may query whether this plugin
can be loaded.
Filename
--------
When OpenHBCI is asked to create a medium of the type "DDVCard" it performs
these actions:
- check whether a plugin is already loaded which provides this type
- if it is not:
- take the name of the medium type (in this case "DDVCard")
- change it to lower cases (->"ddvcard")
- append the extension used on the running system (on Linux: ".so")
(-> "ddvcard.so")
- look for a file of that name in the system wide OpenHBCI plugin folder.
You can get this folder with the command "openhbci-config --plugins"
So the name of the file must be the lower cased medium type string
plus the shared object file extension used on the current operating system.
Exported Symbols
----------------
The following symbols (see nm(1)) must be defined in any new plugin:
int @PLUGINNAME@_openhbci_plugin_interface_version;
/* This is the plugin interface version of OpenHBCI, which is
necessary so that old plugins can be handled as well. For new
plugins, it has to be set to the current value of
OPENHBCI_PLUGIN_INTERFACE_VERSION */
int @PLUGINNAME@_openhbci_module_current;
int @PLUGINNAME@_openhbci_module_revision;
int @PLUGINNAME@_openhbci_module_age;
/* The above three numbers are the version
number of the given plugin implementation. The three version numbers
are handled in the same way as libtool's versioning system. See the
info pages of libtool. */
HBCI::Error @PLUGINNAME@_registerYourSelf(HBCI::API *api);
/* This is the initialization function for the plugin. See below. */
If any of these symbols cannot be found, the plugin loader interface
will return an error message and refuse to load the plugin.
Please note that @PLUGINNAME@ stands for the name of your plugin (no
capitals). Each exported symbol must have this prefix to avoid namespace
collisions when linking a plugin statically to OpenHBCI.
RegisterYourSelf
----------------
This is the function OpenHBCI uses to initialize the plugin. It may
perform whatever actions it needs to perform.
However, the first thing this function should do is to check the version
of OpenHBCI used and compare it against that version which was used when
the plugin has been compiled.
RULE 1: A plugin should refuse to work if the currently running
version of OpenHBCI is older than that one used to compile the
plugin! In that case, the plugin's function
registerYourSelf() should return an HBCI::Error with error
code [FIXME: Give error code here]. [FIXME: Isn't this a bit
too strict? Shouldn't it be allowed if only the patchlevel
and/or minor changed?]
RULE 2: If the major version number of the running OpenHBCI library differs
from the one used to compile the plugin, then the plugin
should refuse to work, too, and return a HBCI::Error with erro
code [FIXME: give error code here.]
If the version check succeeds, then this function should instantiate
an object of a class that inherits HBCI::MediumPlugin (in our example
this is HBCI::DDVCardPlugin) and call api->registerMediumPlugin() with
this object, thus registering the new plugin.
Important Classes
=================
When writing your own MediumPlugin you will find the following classes
helpful:
- HBCI::Medium -- Abstract base class for any security medium
- HBCI::Plugin -- Abstract base class for any plugin
- HBCI::MediumPlugin -- Abstract base class for medium plugin
A nice example of how to create a plugin is the RDHFile plugin located
in "src/plugins/keyfile".
Note: The class PluginFile is not intended to be inherited by a
plugin, despite its name. Instead, that class is used internally by
OpenHBCI's plugin loader interface to manage the known plugins. You
probably do not need to inherit that class.
Caveats
=======
Most likely your new medium plugin is written in C++. However, to be
able to lookup the exported symbols through dlsym(3), the exported
symbols must be declared with the 'extern "C"' binding
prefix. Otherwise, due to each C++ compiler's name mangling, it would
not be possible to lookup the symbols by dlsym(). So you need to use
the binding prefix `extern "C"`. The following example will work:
-------------------------------------------------X8
extern "C" {
int @PLUGINNAME@_openhbci_plugin_interface_version = OPENHBCI_PLUGIN_INTERFACE_VERSION;
int @PLUGINNAME@_openhbci_module_current=DDVCARD_MODULE_CURRENT;
int @PLUGINNAME@_openhbci_module_revision=DDVCARD_MODULE_REVISION;
int @PLUGINNAME@_openhbci_module_age=DDVCARD_MODULE_AGE;
HBCI::Error @PLUGINNAME@_registerYourSelf(HBCI::API *api) {
// do initialization here
}
}; // extern "C"
-------------------------------------------------X8
Please note that ONLY these symbols (functions, variables) MUST be
declared within the 'extern "C"' statement. All other symbols MUST
NOT!
More Usefull Rules
==================
Unfortunately old GCC compilers (before 3.0) have very big problems with code
that loads C++-libraries via dlopen(3). These problems make the new plugin
system of OpenHBCI useles on those systems.
However, in such a case OpenHBCI is able to statically link against your
plugin, if you respect the following additional rules:
RULE 1: Your makefiles must include rules that additionally allow building of
a conveniance library. Normally your Makefile.am looks like this:
-------------------------------------------------X8
plugindir=@PLUGIN_PATH@/media
plugin_LTLIBRARIES=ddvcard.la
ddvcard_la_SOURCES=ddvcard.cpp mediumddv.cpp
ddvcard_la_LDFLAGS=-module -version-info 0:0:0
ddvcard_la_LIBADD=@libchipcard_libs@
-------------------------------------------------X8
This builds the plugin module.
Now you should add the following to your Makefile.am:
-------------------------------------------------X8
noinst_LTLIBRARIES=libddvcard.la
libddvcard_la_SOURCES=ddvcard.cpp mediumddv.cpp
libddvcard_la_LIBADD=@libchipcard_libs@
-------------------------------------------------X8
As you can see these rules are the same as those for building the
module, except that the options "-module" and "-version-info" are
missing. These rules create a standard library against which OpenHBCI
can be linked.
RULE 2: The main folder of your package should contain a file named
"LIBRARY". This should contain the relative path and name of the
library for statical linking (e.g. "src/libddvcard.la").
If this file is missing then the name of the folder containing the
plugin plus ".la" is used.
RULE 3: The main folder of your package should contain a file named
"PLUGINNAME" which holds the name of the plugin in lower cased
(e.g. "ddvcard").
If this file is missing then the name of the folder containing the
plugin is used.
Examples
========
Please have a look at the plugin "openhbci-ddvcard".
You can get it
- via CVS:
"cvs -d:anonymous@cvs.openhbci.sf.net:/cvsroot/openhbci login"
<Leave Password empty>
"cvs -d:anonymous@cvs.openhbci.sf.net:/cvsroot/openhbci co plugins"
<THIS DOWNLOADS THE PLUGINS>
- later from the OpenHBCI site (http://www.openhbci.de)