lobster Plugins ======= As lobster was about to become the second PHP daemon reading the Postfix/Dovecot server logs, I decided to develop lobster as a plugin-based framework for reading Postfix/Dovecot logs and taking action based upon what is found in the logs. lobster reads the config file, daemonizes, and then gathers data and then feeds that data to plugins, which do all the actual mail service things. Plugins focus on the actual issue to be addressed. The main documentation for developing plugins consists of this information, and the source code for the plugins that ship with lobster. Creating New Plugins: --------------------- All plugins are expected to be in a directory named 'plugins'. All enabled plugins should be symlinked in 'plugins-enabled'. Hooks: ------ lobster provides four hooks. 1) ident (filter): All plugins MUST hook ident. Adds plugin to ident string. 2) init (action): Called when lobster starts up. 3) process (action) Called when new log data is collected. 4) shutdown (action) Called at start of lobster shutdown. Code: ----- Every plugin MUST have its own namespace within 'Plugs': namespace Plugs\ExamplePlugin; Constants that MUST be provided: define(__NAMESPACE__.'\NAME', 'ExamplePlugin'); // Name of plugin define(__NAMESPACE__.'\DESCRIPTION', 'Blah blah blah''); // Description define(__NAMESPACE__.'\VERSION', '0.0.0'); // Version of plugin define(__NAMESPACE__.'\REQUIRED_PHP_VERSION', '5.3.0'); define(__NAMESPACE__.'\ID', __NAMESPACE__); define(__NAMESPACE__.'\FILE', __FILE__); define(__NAMESPACE__.'\URL', 'http://example.com/example/');// URL to plugin define(__NAMESPACE__.'\TYPE', 'policy'); define(__NAMESPACE__.'\PROVIDES', __NAMESPACE__); define(__NAMESPACE__.'\REQUIRES', ''); define(__NAMESPACE__.'\AUTHOR_NAME', 'John Q. Public'); // Author info define(__NAMESPACE__.'\AUTHOR_EMAIL', 'jqp@example.net'); // Author info define(__NAMESPACE__.'\AUTHOR_URL', 'http://example.net/jqp');// Author info Plugins MUST be executed only within lobster or another suitable PHP script. defined('VERSION') or die( 'Error: Plugin '.substr(__NAMESPACE__, strpos(__NAMESPACE__, '\\')+1). ' cannot be directly executed.'); if (version_compare(phpversion(), __NAMESPACE__.'\REQUIRED_PHP_VERSION') < 0) return FALSE; All plugins MUST Register plugin information: $plugsystem->register_plugin(__NAMESPACE__.'\id', array(__NAMESPACE__.'\VERSION', __NAMESPACE__.'\REQUIRED_PHP_VERSION', __NAMESPACE__.'\ID', __NAMESPACE__.'\FILE', __NAMESPACE__.'\NAME', __NAMESPACE__.'\DESCRIPTION', __NAMESPACE__.'\URL', __NAMESPACE__.'\TYPE', __NAMESPACE__.'\AUTHOR_NAME', __NAMESPACE__.'\AUTHOR_EMAIL', __NAMESPACE__.'\AUTHOR_URL')); Every plugin class must contain the ident method: function ident($idstring='') { if ($idstring) $idstring .= ' '; return $idstring.__NAMESPACE__.'\NAME'; } When a plugin loads, it must hook the ident filter: $plugsystem->add_filter('ident', array($plug, 'ident')); Resources: You should whenever possible, use the root classes Postfix and Dovecot. These classes provide objects for Postfix and Dovecot that are managed by lobster. You should whenever possible, use the $db object provided and managed by lobster.