summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2015-11-21 14:51:17 +0100
committerJörg Frings-Fürst <debian@jff-webhosting.net>2015-11-21 14:51:17 +0100
commitbb9bc9051629c3319c56785c2f4ae0e605d76329 (patch)
treeec393eb145e5a7d43909bdfc43cdeaa28c4e434a /modules
Initial import of bitz-server version 0.1.6-1
Diffstat (limited to 'modules')
-rw-r--r--modules/Makefile.am3
-rw-r--r--modules/echo/Makefile.am9
-rw-r--r--modules/echo/echo.cpp55
-rw-r--r--modules/echo/echo.h54
-rw-r--r--modules/modpy/Makefile.am18
-rw-r--r--modules/modpy/interface.cpp160
-rw-r--r--modules/modpy/interface.h39
-rw-r--r--modules/modpy/modules/Makefile.am11
-rw-r--r--modules/modpy/modules/modpy.py42
-rw-r--r--modules/modpy/py.cpp265
-rw-r--r--modules/modpy/py.h70
11 files changed, 726 insertions, 0 deletions
diff --git a/modules/Makefile.am b/modules/Makefile.am
new file mode 100644
index 0000000..c52d720
--- /dev/null
+++ b/modules/Makefile.am
@@ -0,0 +1,3 @@
+## modules/
+SUBDIRS = echo modpy
+
diff --git a/modules/echo/Makefile.am b/modules/echo/Makefile.am
new file mode 100644
index 0000000..3236ad7
--- /dev/null
+++ b/modules/echo/Makefile.am
@@ -0,0 +1,9 @@
+# modules/echo
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/src
+
+modlibdir = $(pkglibdir)/modules
+modlib_LTLIBRARIES = mod_echo.la
+mod_echo_la_LDFLAGS = -module -avoid-version
+mod_echo_la_SOURCES = \
+ echo.h echo.cpp
+
diff --git a/modules/echo/echo.cpp b/modules/echo/echo.cpp
new file mode 100644
index 0000000..a8496c5
--- /dev/null
+++ b/modules/echo/echo.cpp
@@ -0,0 +1,55 @@
+/*
+ * bitz-server, An ICAP server implementation in C++
+ * Copyright (C) 2012 Uditha Atukorala
+ *
+ * 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 3 of the License, or
+ * (at your option) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "echo.h"
+
+
+namespace bitz {
+
+ Echo::Echo() : Modifier() { }
+ Echo::~Echo() { }
+
+
+ icap::Response * Echo::modify( icap::Request * request ) throw() {
+
+ icap::Response * response;
+ icap::payload_t payload;
+
+ // copy payload from request
+ payload.req_header = request->payload().req_header;
+ payload.req_body = request->payload().req_body;
+ payload.res_header = request->payload().res_header;
+ payload.res_body = request->payload().res_body;
+
+
+ response = new icap::Response( icap::ResponseHeader::OK );
+ response->payload( payload );
+
+ return response;
+
+ }
+
+
+ icap::Response * Echo::preview( icap::Request * request ) throw() {
+ // 100 - continue always
+ return new icap::Response( icap::ResponseHeader::CONTINUE );
+ }
+
+} /* end of namespace bitz */
+
diff --git a/modules/echo/echo.h b/modules/echo/echo.h
new file mode 100644
index 0000000..87df312
--- /dev/null
+++ b/modules/echo/echo.h
@@ -0,0 +1,54 @@
+/*
+ * bitz-server, An ICAP server implementation in C++
+ * Copyright (C) 2012 Uditha Atukorala
+ *
+ * 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 3 of the License, or
+ * (at your option) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef BITZ_ECHO_H
+#define BITZ_ECHO_H
+
+#include <bitz/modifier.h>
+
+
+namespace bitz {
+
+ class Echo : public Modifier {
+ public:
+ Echo();
+ virtual ~Echo();
+
+ icap::Response * modify( icap::Request * request ) throw();
+ icap::Response * preview( icap::Request * request ) throw();
+
+ private:
+
+ };
+
+} /* end of namespace bitz */
+
+
+/* class factories */
+
+extern "C" bitz::Modifier * create() {
+ return new bitz::Echo;
+}
+
+extern "C" void destroy( bitz::Modifier * m ) {
+ delete m;
+}
+
+#endif /* !BITZ_ECHO_H */
+
diff --git a/modules/modpy/Makefile.am b/modules/modpy/Makefile.am
new file mode 100644
index 0000000..eccb2a2
--- /dev/null
+++ b/modules/modpy/Makefile.am
@@ -0,0 +1,18 @@
+# modules/modpy
+
+SUBDIRS = modules
+
+if MODPY
+modlibdir = $(pkglibdir)/modules
+modlib_LTLIBRARIES = mod_py.la
+mod_py_la_LDFLAGS = -module -avoid-version
+mod_py_la_SOURCES = \
+ py.h py.cpp \
+ interface.h interface.cpp
+
+AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/src \
+ ${PYTHON_INCLUDES} ${libconfig_CFLAGS} ${log4cpp_CFLAGS}
+
+mod_py_la_LIBADD = ${PYTHON_LIBS}
+endif
+
diff --git a/modules/modpy/interface.cpp b/modules/modpy/interface.cpp
new file mode 100644
index 0000000..948fa5c
--- /dev/null
+++ b/modules/modpy/interface.cpp
@@ -0,0 +1,160 @@
+/*
+ * bitz-server, An ICAP server implementation in C++
+ * Copyright (C) 2012 Uditha Atukorala
+ *
+ * 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 3 of the License, or
+ * (at your option) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "interface.h"
+
+#include <bitz/logger.h>
+#include <icap/request.h>
+#include <icap/response.h>
+#include <iostream>
+
+
+PyObject * bitz_get_request( PyObject * self, PyObject * pyrequest ) {
+
+ PyObject * pyreturn;
+ PyObject * pypayload;
+ icap::Request * request;
+
+ // logger
+ bitz::Logger &logger = bitz::Logger::instance();
+ logger.debug( "[modpy.interface] get_request()" );
+
+ // initialise return dictionary
+ pyreturn = PyDict_New();
+
+ // grab the request object pointer from args
+ void * p = PyCapsule_GetPointer( pyrequest, "request" );
+
+ // sanity check
+ if ( p != NULL ) {
+
+ // construct the request
+ request = static_cast<icap::Request *>(p);
+
+ PyDict_SetItemString( pyreturn, "request", PyString_FromString( request->header()->method().c_str() ) );
+ PyDict_SetItemString( pyreturn, "uri", PyString_FromString( request->header()->uri().c_str() ) );
+ PyDict_SetItemString( pyreturn, "protocol", PyString_FromString( request->header()->protocol().c_str() ) );
+
+ // payload dictionary
+ pypayload = PyDict_New();
+ PyDict_SetItemString( pypayload, "req_header", PyString_FromStringAndSize( request->payload().req_header.c_str(), request->payload().req_header.size() ) );
+ PyDict_SetItemString( pypayload, "req_body", PyString_FromStringAndSize( request->payload().req_body.c_str(), request->payload().req_body.size() ) );
+ PyDict_SetItemString( pypayload, "res_header", PyString_FromStringAndSize( request->payload().res_header.c_str(), request->payload().res_header.size() ) );
+ PyDict_SetItemString( pypayload, "res_body", PyString_FromStringAndSize( request->payload().res_body.c_str(), request->payload().res_body.size() ) );
+ PyDict_SetItemString( pypayload, "ieof", PyBool_FromLong( request->payload().ieof ) );
+
+ PyDict_SetItemString( pyreturn, "payload", pypayload );
+
+ // cleanup
+ Py_DECREF( pypayload );
+
+ } else {
+ logger.warn( "[modpy.interface] failed to get request object pointer" );
+ }
+
+ return pyreturn;
+
+}
+
+
+PyObject * bitz_get_response_from_status( PyObject * self, PyObject * args ) {
+
+ PyObject * pyresponse;
+ icap::Response * response;
+
+ unsigned int resp_status;
+
+ // logger
+ bitz::Logger &logger = bitz::Logger::instance();
+ logger.debug( "[modpy.interface] get_response_from_status()" );
+
+ // parse args
+ if ( PyArg_ParseTuple( args, "I", &resp_status ) ) {
+ response = new icap::Response( (icap::ResponseHeader::status_t) resp_status );
+ } else {
+ logger.warn( "[modpy.interface] failed to parse arguments" );
+ response = new icap::Response( icap::ResponseHeader::SERVER_ERROR );
+ }
+
+ // convert the response into a capsule
+ pyresponse = PyCapsule_New( (void *) response, "response", NULL );
+
+ return pyresponse;
+
+}
+
+
+PyObject * bitz_get_response( PyObject * self, PyObject * args ) {
+
+ PyObject * pyresponse;
+ PyObject * pypayload;
+ icap::Response * response = NULL;
+
+ unsigned int resp_status;
+ icap::payload_t payload;
+
+ // vars to ferry across strings from python dictionary to c++
+ char * pybuffer;
+ Py_ssize_t pybuflen;
+
+
+ // logger
+ bitz::Logger &logger = bitz::Logger::instance();
+ logger.debug( "[modpy.interface] get_response()" );
+
+ // parse args
+ if ( PyArg_ParseTuple( args, "IO!", &resp_status, &PyDict_Type, &pypayload ) ) {
+
+ // copy strings from python dictionary
+ PyString_AsStringAndSize( PyDict_GetItemString( pypayload, "req_header" ), &pybuffer, &pybuflen );
+ payload.req_header.assign( pybuffer, pybuflen );
+
+ PyString_AsStringAndSize( PyDict_GetItemString( pypayload, "req_body" ), &pybuffer, &pybuflen );
+ payload.req_body.assign( pybuffer, pybuflen );
+
+ PyString_AsStringAndSize( PyDict_GetItemString( pypayload, "res_header" ), &pybuffer, &pybuflen );
+ payload.res_header.assign( pybuffer, pybuflen );
+
+ PyString_AsStringAndSize( PyDict_GetItemString( pypayload, "res_body" ), &pybuffer, &pybuflen );
+ payload.res_body.assign( pybuffer, pybuflen );
+
+ // copy other data types from python dictionary
+ payload.ieof = PyBool_Check( PyDict_GetItemString( pypayload, "ieof" ) );
+
+ // construct the response object
+ response = new icap::Response( (icap::ResponseHeader::status_t) resp_status );
+ response->payload( payload );
+
+ } else {
+ logger.warn( "[modpy.interface] failed to parse arguments" );
+ }
+
+ // sanity check
+ if ( response == NULL ) {
+ response = new icap::Response( icap::ResponseHeader::SERVER_ERROR );
+ }
+
+ // convert the response into a capsule
+ pyresponse = PyCapsule_New( (void *) response, "response", NULL );
+
+ return pyresponse;
+
+}
+
+
diff --git a/modules/modpy/interface.h b/modules/modpy/interface.h
new file mode 100644
index 0000000..315a2f6
--- /dev/null
+++ b/modules/modpy/interface.h
@@ -0,0 +1,39 @@
+/*
+ * bitz-server, An ICAP server implementation in C++
+ * Copyright (C) 2012 Uditha Atukorala
+ *
+ * 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 3 of the License, or
+ * (at your option) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef BITZ_MODPY_INTERFACE_H
+#define BITZ_MODPY_INTERFACE_H
+
+#include <Python.h>
+#include <stddef.h>
+
+
+PyObject * bitz_get_request( PyObject * self, PyObject * pyrequest );
+PyObject * bitz_get_response( PyObject * self, PyObject * args );
+PyObject * bitz_get_response_from_status( PyObject * self, PyObject * args);
+
+static PyMethodDef bitz_methods[] = {
+ { "get_request", bitz_get_request, METH_O, "Convert a capsule request into a python dictionary" },
+ { "get_response", bitz_get_response, METH_VARARGS, "Get a response capsule (takes in status and payload dictionary as args)" },
+ { "get_response_from_status", bitz_get_response_from_status, METH_VARARGS, "Get a response capsule from a response status" },
+ { NULL, NULL, 0, NULL }
+};
+
+#endif /* !BITZ_MODPY_INTERFACE_H */
+
diff --git a/modules/modpy/modules/Makefile.am b/modules/modpy/modules/Makefile.am
new file mode 100644
index 0000000..9292d1d
--- /dev/null
+++ b/modules/modpy/modules/Makefile.am
@@ -0,0 +1,11 @@
+# modules/modpy/modules
+
+# extra dist files
+EXTRA_DIST = \
+ modpy.py
+
+if MODPY
+modpydir = $(pkglibdir)/modules/modpy
+modpy_DATA = modpy.py
+endif
+
diff --git a/modules/modpy/modules/modpy.py b/modules/modpy/modules/modpy.py
new file mode 100644
index 0000000..9a5e578
--- /dev/null
+++ b/modules/modpy/modules/modpy.py
@@ -0,0 +1,42 @@
+#
+# modpy.py
+# Copyright (c) 2013 Uditha Atukorala
+#
+
+import bitz
+
+def init():
+ print "init() called";
+
+def cleanup():
+ print "cleanup() called";
+
+def preview( request ):
+ request = bitz.get_request( request );
+ req_payload = request['payload'];
+ print "preview payload: \r\n", req_payload;
+
+ # response
+ if req_payload['ieof']:
+ response = bitz.get_response_from_status( 204 );
+ else:
+ response = bitz.get_response_from_status( 100 );
+
+ return response;
+
+def modify( request ):
+ request = bitz.get_request( request );
+ req_payload = request['payload'];
+ print "modify payload: \r\n", req_payload;
+
+ # response
+ resp_payload = {};
+ resp_payload['req_header'] = req_payload['req_header'];
+ resp_payload['req_body'] = req_payload['req_body'];
+ resp_payload['res_header'] = req_payload['res_header'];
+ resp_payload['res_body'] = req_payload['res_body'];
+ resp_payload['ieof'] = True;
+
+ response = bitz.get_response( 200, resp_payload );
+ return response;
+
diff --git a/modules/modpy/py.cpp b/modules/modpy/py.cpp
new file mode 100644
index 0000000..51cb38f
--- /dev/null
+++ b/modules/modpy/py.cpp
@@ -0,0 +1,265 @@
+/*
+ * bitz-server, An ICAP server implementation in C++
+ * Copyright (C) 2012 Uditha Atukorala
+ *
+ * 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 3 of the License, or
+ * (at your option) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "py.h"
+#include "interface.h"
+
+#include <bitz/config.h>
+#include <bitz/logger.h>
+
+
+namespace bitz {
+
+ Py::Py() : Modifier() {
+
+ // defaults
+ _pymodule = NULL;
+
+ // initialise Py::config_t values
+ _config.module_name = "modpy";
+ _config.module_path = "";
+
+ // load configs
+ load_configs();
+
+ // initialise python
+ init_python();
+
+ }
+
+
+ Py::~Py() {
+
+ // cleanup python
+ cleanup_python();
+
+ }
+
+
+ icap::Response * Py::modify( icap::Request * request ) throw() {
+
+ // get the modify response
+ return python_response( request, "modify" );
+
+ }
+
+
+ icap::Response * Py::preview( icap::Request * request ) throw() {
+
+ // get the preview response
+ return python_response( request, "preview" );
+
+ }
+
+
+ void Py::load_configs() throw() {
+
+ std::string s;
+ Config &server_config = Config::instance();
+
+ // interface module name
+ s = server_config.module_config( "modpy", "module_name" );
+ if ( s != "" ) {
+ _config.module_name = s;
+ }
+
+ // module lookup path
+ _config.module_path = server_config.module_config( "modpy", "module_path" );
+
+ }
+
+
+ void Py::init_python() throw() {
+
+ PyObject * sys_path;
+ PyObject * pymodule_path, * pymodule_name;
+ PyObject * pymethod;
+ PyObject * pyreturn;
+
+ // logger
+ Logger &logger = Logger::instance();
+
+ // python core
+ Py_Initialize();
+
+ // bitz python module
+ if ( Py_InitModule( "bitz", bitz_methods ) == NULL ) {
+ logger.warn( "[modpy] failed to init C interface module: bitz" );
+ }
+
+ // setup python environment
+ if ( _config.module_path != "" ) {
+
+ logger.debug( std::string( "[modpy] appending to sys.path, module_path: " ).append( _config.module_path ) );
+
+ sys_path = PySys_GetObject( (char *) "path" );
+ pymodule_path = PyString_FromString( _config.module_path.c_str() );
+ PyList_Append( sys_path, pymodule_path );
+
+ }
+
+ // load the interface module
+ logger.debug( std::string( "[modpy] interface module: " ).append( _config.module_name ) );
+
+ pymodule_name = PyString_FromString( _config.module_name.c_str() );
+ _pymodule = PyImport_Import( pymodule_name );
+
+ if ( _pymodule != NULL ) {
+
+ logger.debug( "[modpy] interface module loaded successfully" );
+
+ // call init() in the interface module
+ pymethod = PyObject_GetAttrString( _pymodule, "init" );
+
+ if ( pymethod && PyCallable_Check( pymethod ) ) {
+ pyreturn = PyObject_CallObject( pymethod, NULL );
+ Py_DECREF( pyreturn );
+ } else {
+ logger.warn ( "[modpy] failed to call init() in interface module" );
+ }
+
+ Py_DECREF( pymethod );
+
+ } else {
+ logger.warn( "[modpy] failed to load interface module" );
+ }
+
+
+ // cleanup
+ Py_DECREF( pymodule_name );
+ Py_DECREF( pymodule_path );
+ Py_DECREF( sys_path );
+
+ }
+
+
+ void Py::cleanup_python() throw() {
+
+ PyObject * pymethod;
+ PyObject * pyreturn;
+
+ // logger
+ Logger &logger = Logger::instance();
+
+
+ // cleanup
+ if ( _pymodule != NULL ) {
+
+ // call cleanup() in the interface module
+ pymethod = PyObject_GetAttrString( _pymodule, "cleanup" );
+
+ if ( pymethod && PyCallable_Check( pymethod ) ) {
+ pyreturn = PyObject_CallObject( pymethod, NULL );
+ Py_DECREF( pyreturn );
+ } else {
+ logger.warn ( "[modpy] failed to call cleanup() in interface module" );
+ }
+
+ Py_DECREF( pymethod );
+ Py_DECREF( _pymodule );
+
+ }
+
+ // finalise python core
+ Py_Finalize();
+
+ }
+
+
+ icap::Response * Py::python_response( icap::Request * request, const std::string &method ) throw() {
+
+ /*
+ * notes:
+ * + pass icap::Request to python module as a PyCapsule object
+ * so it can be used to grab the data needed using the C/C++ interface.
+ * + process data (within the python module) and use the C/C++ interface
+ * to create a icap::Response and pass it back to this method
+ * using a PyCapsule object
+ */
+
+ icap::Response * response;
+
+ PyObject * pymethod;
+ PyObject * pyargs;
+ PyObject * pyrequest, * pyresponse;
+
+ // logger
+ Logger &logger = Logger::instance();
+
+ // initialise the response object
+ response = NULL;
+
+ // check for the interface module
+ if ( _pymodule != NULL ) {
+
+ /* call the [method]() in the interface module */
+ pymethod = PyObject_GetAttrString( _pymodule, method.c_str() );
+ pyargs = PyTuple_New( 1 );
+ pyrequest = PyCapsule_New( (void *) request, "request", NULL );
+ PyTuple_SetItem( pyargs, 0, pyrequest );
+
+ if ( pymethod && PyCallable_Check( pymethod ) ) {
+
+ // get the response capsule
+ pyresponse = PyObject_CallObject( pymethod, pyargs );
+
+ // sanity check
+ if ( pyresponse != NULL ) {
+
+ void * p = PyCapsule_GetPointer( pyresponse, "response" );
+
+ // sanity check
+ if ( p != NULL ) {
+
+ // construct the response
+ response = static_cast<icap::Response *>(p);
+
+ } else {
+ logger.warn( std::string( "[modpy] invalid capsule response, method: " ).append( method ) );
+ }
+
+ Py_DECREF( pyresponse );
+
+ } else {
+ logger.warn( std::string( "[modpy] response is NULL, method: " ).append( method ) );
+ }
+
+
+ } else {
+ logger.warn ( std::string( "[modpy] failed to call the method in interface module, method: " ).append( method ) );
+ }
+
+ // cleanup
+ // pyrequest is created from the reference passed in
+ Py_DECREF( pyargs );
+ Py_DECREF( pymethod );
+
+ }
+
+ // sanity check
+ if ( response == NULL ) {
+ response = new icap::Response( icap::ResponseHeader::SERVER_ERROR );
+ }
+
+ return response;
+
+ }
+
+} /* end of namespace bitz */
+
diff --git a/modules/modpy/py.h b/modules/modpy/py.h
new file mode 100644
index 0000000..358c36f
--- /dev/null
+++ b/modules/modpy/py.h
@@ -0,0 +1,70 @@
+/*
+ * bitz-server, An ICAP server implementation in C++
+ * Copyright (C) 2012 Uditha Atukorala
+ *
+ * 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 3 of the License, or
+ * (at your option) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef BITZ_PY_H
+#define BITZ_PY_H
+
+#include <Python.h>
+
+#include <bitz/modifier.h>
+
+
+namespace bitz {
+
+ class Py : public Modifier {
+ public:
+
+ struct config_t {
+ std::string module_path;
+ std::string module_name;
+ };
+
+ Py();
+ virtual ~Py();
+
+ icap::Response * modify( icap::Request * request ) throw();
+ icap::Response * preview( icap::Request * request ) throw();
+
+ private:
+ config_t _config;
+ PyObject * _pymodule;
+
+ void load_configs() throw();
+ void init_python() throw();
+ void cleanup_python() throw();
+
+ icap::Response * python_response( icap::Request * request, const std::string &method ) throw();
+
+ };
+
+} /* end of namespace bitz */
+
+
+/* class factories */
+
+extern "C" bitz::Modifier * create() {
+ return new bitz::Py;
+}
+
+extern "C" void destroy( bitz::Modifier * m ) {
+ delete m;
+}
+
+#endif /* !BITZ_PY_H */
+