aboutsummaryrefslogtreecommitdiffstats
path: root/src/manager
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2007-09-11 15:22:02 +0000
committerMartin Willi <martin@strongswan.org>2007-09-11 15:22:02 +0000
commit965e99b5bff26d1f43273214a5f44e31611018e7 (patch)
tree8fc01a4fb5e9f781b1d3ef7d83959002749d2a67 /src/manager
parentf0c156fbc91e212852971f690da677a51ba97397 (diff)
downloadstrongswan-965e99b5bff26d1f43273214a5f44e31611018e7.tar.bz2
strongswan-965e99b5bff26d1f43273214a5f44e31611018e7.tar.xz
first revision of new manager webapp
Diffstat (limited to 'src/manager')
-rw-r--r--src/manager/Makefile.am33
-rw-r--r--src/manager/controller/auth_controller.c125
-rw-r--r--src/manager/controller/auth_controller.h47
-rw-r--r--src/manager/controller/gateway_controller.c147
-rw-r--r--src/manager/controller/gateway_controller.h47
-rw-r--r--src/manager/controller/static_controller.c103
-rw-r--r--src/manager/controller/static_controller.h47
-rw-r--r--src/manager/controller/status_controller.c136
-rw-r--r--src/manager/controller/status_controller.h47
-rw-r--r--src/manager/database.c195
-rw-r--r--src/manager/database.h69
-rw-r--r--src/manager/gateway.c153
-rw-r--r--src/manager/gateway.h58
-rw-r--r--src/manager/lib/context.h47
-rw-r--r--src/manager/lib/controller.h75
-rw-r--r--src/manager/lib/dispatcher.c348
-rw-r--r--src/manager/lib/dispatcher.h78
-rw-r--r--src/manager/lib/enumerator.h49
-rw-r--r--src/manager/lib/request.c306
-rw-r--r--src/manager/lib/request.h73
-rw-r--r--src/manager/lib/response.c223
-rw-r--r--src/manager/lib/response.h95
-rw-r--r--src/manager/lib/session.c185
-rw-r--r--src/manager/lib/session.h75
-rw-r--r--src/manager/lib/template.c138
-rw-r--r--src/manager/lib/template.h76
-rw-r--r--src/manager/main.c62
-rw-r--r--src/manager/manager.c160
-rw-r--r--src/manager/manager.h93
-rw-r--r--src/manager/templates/auth/login.cs15
-rw-r--r--src/manager/templates/auth/logout.cs0
-rw-r--r--src/manager/templates/footer.cs2
-rw-r--r--src/manager/templates/gateway/list.cs13
-rw-r--r--src/manager/templates/header.cs8
-rw-r--r--src/manager/templates/static/style.css188
-rw-r--r--src/manager/templates/status/ikesalist.cs1
36 files changed, 3517 insertions, 0 deletions
diff --git a/src/manager/Makefile.am b/src/manager/Makefile.am
new file mode 100644
index 000000000..d86110e46
--- /dev/null
+++ b/src/manager/Makefile.am
@@ -0,0 +1,33 @@
+ipsec_PROGRAMS = manager
+
+manager_SOURCES = \
+main.c manager.c manager.h gateway.h gateway.c database.h database.c \
+controller/auth_controller.c controller/auth_controller.h \
+controller/static_controller.c controller/static_controller.h \
+controller/status_controller.c controller/status_controller.h \
+controller/gateway_controller.c controller/gateway_controller.h
+
+manager_LDADD = $(top_builddir)/src/manager/libappserv.la -lsqlite3
+
+
+
+lib_LTLIBRARIES = libappserv.la
+
+libappserv_la_SOURCES = \
+lib/context.h lib/dispatcher.c lib/request.h lib/response.h lib/session.h \
+lib/controller.h lib/dispatcher.h lib/request.c lib/response.c lib/session.c \
+lib/template.h lib/template.c
+
+libappserv_la_LDFLAGS = -lstrongswan -lfcgi -lpthread -lneo_cs -lneo_utl
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/manager/lib -I/usr/include/ClearSilver
+
+
+ipsec_templatesdir = ${ipsecdir}/templates
+ipsec_templates_DATA = templates/header.cs templates/footer.cs
+
+ipsec_templates_authdir = ${ipsec_templatesdir}/auth
+ipsec_templates_auth_DATA = templates/auth/login.cs templates/auth/logout.cs
+
+ipsec_templates_staticdir = ${ipsec_templatesdir}/static
+ipsec_templates_static_DATA = templates/static/style.css
diff --git a/src/manager/controller/auth_controller.c b/src/manager/controller/auth_controller.c
new file mode 100644
index 000000000..1026b5eeb
--- /dev/null
+++ b/src/manager/controller/auth_controller.c
@@ -0,0 +1,125 @@
+/**
+ * @file auth_controller.c
+ *
+ * @brief Implementation of auth_controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "auth_controller.h"
+#include "../manager.h"
+
+#include <template.h>
+
+#include <library.h>
+
+
+typedef struct private_auth_controller_t private_auth_controller_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_auth_controller_t {
+
+ /**
+ * public functions
+ */
+ auth_controller_t public;
+
+ /**
+ * manager instance
+ */
+ manager_t *manager;
+};
+
+static void login(private_auth_controller_t *this,
+ request_t *request, response_t *response)
+{
+ template_t *t = template_create("templates/auth/login.cs");
+ t->set(t, "action", "check");
+ t->render(t, response);
+ t->destroy(t);
+}
+
+static void check(private_auth_controller_t *this,
+ request_t *request, response_t *response)
+{
+ char *username, *password;
+
+ username = request->get_post_data(request, "username");
+ password = request->get_post_data(request, "password");
+ if (username && password &&
+ this->manager->login(this->manager, username, password))
+ {
+ response->redirect(response, "status/test");
+ }
+ else
+ {
+ response->redirect(response, "auth/login");
+ }
+}
+
+static void logout(private_auth_controller_t *this,
+ request_t *request, response_t *response)
+{
+ this->manager->logout(this->manager);
+ response->redirect(response, "auth/login");
+}
+
+/**
+ * Implementation of controller_t.get_name
+ */
+static char* get_name(private_auth_controller_t *this)
+{
+ return "auth";
+}
+
+/**
+ * Implementation of controller_t.get_handler
+ */
+static controller_handler_t get_handler(private_auth_controller_t *this, char *name)
+{
+ if (streq(name, "login")) return (controller_handler_t)login;
+ if (streq(name, "check")) return (controller_handler_t)check;
+ if (streq(name, "logout")) return (controller_handler_t)logout;
+ return NULL;
+}
+
+/**
+ * Implementation of controller_t.destroy
+ */
+static void destroy(private_auth_controller_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+controller_t *auth_controller_create(context_t *context, void *param)
+{
+ private_auth_controller_t *this = malloc_thing(private_auth_controller_t);
+
+ this->public.controller.get_name = (char*(*)(controller_t*))get_name;
+ this->public.controller.get_handler = (controller_handler_t(*)(controller_t*,char*))get_handler;
+ this->public.controller.destroy = (void(*)(controller_t*))destroy;
+
+ this->manager = (manager_t*)context;
+
+ return &this->public.controller;
+}
+
diff --git a/src/manager/controller/auth_controller.h b/src/manager/controller/auth_controller.h
new file mode 100644
index 000000000..c90546a17
--- /dev/null
+++ b/src/manager/controller/auth_controller.h
@@ -0,0 +1,47 @@
+/**
+ * @file auth_controller.h
+ *
+ * @brief Interface of auth_controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef AUTH_CONTROLLER_H_
+#define AUTH_CONTROLLER_H_
+
+
+#include <controller.h>
+
+typedef struct auth_controller_t auth_controller_t;
+
+/**
+ * @brief Authentication controller.
+ */
+struct auth_controller_t {
+
+ /**
+ * Implements controller_t interface.
+ */
+ controller_t controller;
+};
+
+/**
+ * @brief Create a auth_controller controller instance.
+ */
+controller_t *auth_controller_create(context_t *context, void *param);
+
+#endif /* AUTH_CONTROLLER_H_ */
diff --git a/src/manager/controller/gateway_controller.c b/src/manager/controller/gateway_controller.c
new file mode 100644
index 000000000..32576216e
--- /dev/null
+++ b/src/manager/controller/gateway_controller.c
@@ -0,0 +1,147 @@
+/**
+ * @file gateway_controller.c
+ *
+ * @brief Implementation of gateway_controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "gateway_controller.h"
+#include "../manager.h"
+#include "../gateway.h"
+
+#include <template.h>
+
+#include <library.h>
+
+
+typedef struct private_gateway_controller_t private_gateway_controller_t;
+
+/**
+ * private data of the gateway_controller
+ */
+struct private_gateway_controller_t {
+
+ /**
+ * public functions
+ */
+ gateway_controller_t public;
+
+ /**
+ * manager instance
+ */
+ manager_t *manager;
+
+};
+
+static void list(private_gateway_controller_t *this,
+ request_t *request, response_t *response)
+{
+ template_t *t;
+ enumerator_t *enumerator;
+ char *name, *address;
+ int id, port;
+
+ t = template_create("templates/gateway/list.cs");
+ enumerator = this->manager->create_gateway_enumerator(this->manager);
+ while (enumerator->enumerate(enumerator, &id, &name, &port, &address))
+ {
+ t->setf(t, "gateways.%d.name=%s", id, name);
+ if (port)
+ {
+ t->setf(t, "gateways.%d.address=tcp://%s:%d", id, address, port);
+ }
+ else
+ {
+ t->setf(t, "gateways.%d.address=unix://%s", id, address);
+ }
+ }
+ enumerator->destroy(enumerator);
+ t->set(t, "action", "select");
+ t->render(t, response);
+ t->destroy(t);
+}
+
+static void _select(private_gateway_controller_t *this,
+ request_t *request, response_t *response)
+{
+ char *id;
+
+ id = request->get_post_data(request, "gateway");
+ if (id)
+ {
+ if (this->manager->select_gateway(this->manager, atoi(id)))
+ {
+ response->redirect(response, "status/ikesalist");
+ return;
+ }
+ }
+ response->printf(response, "selecting dings failed: %s", id);
+}
+
+/**
+ * redirect to authentication login
+ */
+static void login(private_gateway_controller_t *this,
+ request_t *request, response_t *response)
+{
+ response->redirect(response, "auth/login");
+}
+
+/**
+ * Implementation of controller_t.get_name
+ */
+static char* get_name(private_gateway_controller_t *this)
+{
+ return "gateway";
+}
+
+/**
+ * Implementation of controller_t.get_handler
+ */
+static controller_handler_t get_handler(private_gateway_controller_t *this, char *name)
+{
+ if (!this->manager->logged_in(this->manager)) return (controller_handler_t)login;
+ if (streq(name, "list")) return (controller_handler_t)list;
+ if (streq(name, "select")) return (controller_handler_t)_select;
+ return NULL;
+}
+
+/**
+ * Implementation of controller_t.destroy
+ */
+static void destroy(private_gateway_controller_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+controller_t *gateway_controller_create(context_t *context, void *param)
+{
+ private_gateway_controller_t *this = malloc_thing(private_gateway_controller_t);
+
+ this->public.controller.get_name = (char*(*)(controller_t*))get_name;
+ this->public.controller.get_handler = (controller_handler_t(*)(controller_t*,char*))get_handler;
+ this->public.controller.destroy = (void(*)(controller_t*))destroy;
+
+ this->manager = (manager_t*)context;
+
+ return &this->public.controller;
+}
+
diff --git a/src/manager/controller/gateway_controller.h b/src/manager/controller/gateway_controller.h
new file mode 100644
index 000000000..5872e20e2
--- /dev/null
+++ b/src/manager/controller/gateway_controller.h
@@ -0,0 +1,47 @@
+/**
+ * @file gateway_controller.h
+ *
+ * @brief Interface of gateway_controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef GATEWAY_CONTROLLER_H_
+#define GATEWAY_CONTROLLER_H_
+
+
+#include <controller.h>
+
+typedef struct gateway_controller_t gateway_controller_t;
+
+/**
+ * @brief Status controller.
+ */
+struct gateway_controller_t {
+
+ /**
+ * Implements controller_t interface.
+ */
+ controller_t controller;
+};
+
+/**
+ * @brief Create a gateway_controller controller instance.
+ */
+controller_t *gateway_controller_create(context_t *context, void *param);
+
+#endif /* GATEWAY_CONTROLLER_H_ */
diff --git a/src/manager/controller/static_controller.c b/src/manager/controller/static_controller.c
new file mode 100644
index 000000000..8968c873c
--- /dev/null
+++ b/src/manager/controller/static_controller.c
@@ -0,0 +1,103 @@
+/**
+ * @file static_controller.c
+ *
+ * @brief Implementation of static_controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "static_controller.h"
+#include "../manager.h"
+#include "../gateway.h"
+
+#include <template.h>
+
+#include <library.h>
+
+
+typedef struct private_static_controller_t private_static_controller_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_static_controller_t {
+
+ /**
+ * public functions
+ */
+ static_controller_t public;
+
+ /**
+ * manager instance
+ */
+ manager_t *manager;
+
+};
+
+/**
+ * serve style.css
+ */
+static void style(private_static_controller_t *this,
+ request_t *request, response_t *response)
+{
+ template_t *t = template_create("templates/static/style.css");
+ response->set_content_type(response, "text/css");
+ t->render(t, response);
+ t->destroy(t);
+}
+
+/**
+ * Implementation of controller_t.get_name
+ */
+static char* get_name(private_static_controller_t *this)
+{
+ return "static";
+}
+
+/**
+ * Implementation of controller_t.get_handler
+ */
+static controller_handler_t get_handler(private_static_controller_t *this, char *name)
+{
+ if (streq(name, "style.css")) return (controller_handler_t)style;
+ return NULL;
+}
+
+/**
+ * Implementation of controller_t.destroy
+ */
+static void destroy(private_static_controller_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+controller_t *static_controller_create(context_t *context, void *param)
+{
+ private_static_controller_t *this = malloc_thing(private_static_controller_t);
+
+ this->public.controller.get_name = (char*(*)(controller_t*))get_name;
+ this->public.controller.get_handler = (controller_handler_t(*)(controller_t*,char*))get_handler;
+ this->public.controller.destroy = (void(*)(controller_t*))destroy;
+
+ this->manager = (manager_t*)context;
+
+ return &this->public.controller;
+}
+
diff --git a/src/manager/controller/static_controller.h b/src/manager/controller/static_controller.h
new file mode 100644
index 000000000..8181a7a16
--- /dev/null
+++ b/src/manager/controller/static_controller.h
@@ -0,0 +1,47 @@
+/**
+ * @file static_controller.h
+ *
+ * @brief Interface of static_controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef STATIC_CONTROLLER_H_
+#define STATIC_CONTROLLER_H_
+
+
+#include <controller.h>
+
+typedef struct static_controller_t static_controller_t;
+
+/**
+ * @brief Static controller, serves static files.
+ */
+struct static_controller_t {
+
+ /**
+ * Implements controller_t interface.
+ */
+ controller_t controller;
+};
+
+/**
+ * @brief Create a static_controller controller instance.
+ */
+controller_t *static_controller_create(context_t *context, void *param);
+
+#endif /* STATIC_CONTROLLER_H_ */
diff --git a/src/manager/controller/status_controller.c b/src/manager/controller/status_controller.c
new file mode 100644
index 000000000..eac4b67cf
--- /dev/null
+++ b/src/manager/controller/status_controller.c
@@ -0,0 +1,136 @@
+/**
+ * @file status_controller.c
+ *
+ * @brief Implementation of status_controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "status_controller.h"
+#include "../manager.h"
+#include "../gateway.h"
+
+#include <template.h>
+
+#include <library.h>
+
+
+typedef struct private_status_controller_t private_status_controller_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_status_controller_t {
+
+ /**
+ * public functions
+ */
+ status_controller_t public;
+
+ /**
+ * manager instance
+ */
+ manager_t *manager;
+
+ int count;
+
+};
+
+static void ikesalist(private_status_controller_t *this,
+ request_t *request, response_t *response)
+{
+ char *str;
+ gateway_t *gateway;
+
+ gateway = this->manager->select_gateway(this->manager, 0);
+ str = gateway->request(gateway, "<message type=\"request\" id=\"1\">"
+ "<query>"
+ "<ikesalist/>"
+ "</query>"
+ "</message>");
+
+ response->set_content_type(response, "text/xml");
+ template_t *t = template_create("templates/status/ikesalist.cs");
+ t->set(t, "xml", str);
+ t->render(t, response);
+ t->destroy(t);
+
+ free(str);
+}
+
+/**
+ * redirect to authentication login
+ */
+static void login(private_status_controller_t *this,
+ request_t *request, response_t *response)
+{
+ response->redirect(response, "auth/login");
+}
+
+/**
+ * redirect to gateway selection
+ */
+static void selection(private_status_controller_t *this,
+ request_t *request, response_t *response)
+{
+ response->redirect(response, "gateway/list");
+}
+
+/**
+ * Implementation of controller_t.get_name
+ */
+static char* get_name(private_status_controller_t *this)
+{
+ return "status";
+}
+
+/**
+ * Implementation of controller_t.get_handler
+ */
+static controller_handler_t get_handler(private_status_controller_t *this, char *name)
+{
+ if (!this->manager->logged_in(this->manager)) return (controller_handler_t)login;
+ if (this->manager->select_gateway(this->manager, 0) == NULL) return (controller_handler_t)selection;
+ if (streq(name, "ikesalist")) return (controller_handler_t)ikesalist;
+ return NULL;
+}
+
+/**
+ * Implementation of controller_t.destroy
+ */
+static void destroy(private_status_controller_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+controller_t *status_controller_create(context_t *context, void *param)
+{
+ private_status_controller_t *this = malloc_thing(private_status_controller_t);
+
+ this->public.controller.get_name = (char*(*)(controller_t*))get_name;
+ this->public.controller.get_handler = (controller_handler_t(*)(controller_t*,char*))get_handler;
+ this->public.controller.destroy = (void(*)(controller_t*))destroy;
+
+ this->count = 0;
+ this->manager = (manager_t*)context;
+
+ return &this->public.controller;
+}
+
diff --git a/src/manager/controller/status_controller.h b/src/manager/controller/status_controller.h
new file mode 100644
index 000000000..a736dda83
--- /dev/null
+++ b/src/manager/controller/status_controller.h
@@ -0,0 +1,47 @@
+/**
+ * @file status_controller.h
+ *
+ * @brief Interface of status_controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef STATUS_CONTROLLER_H_
+#define STATUS_CONTROLLER_H_
+
+
+#include <controller.h>
+
+typedef struct status_controller_t status_controller_t;
+
+/**
+ * @brief Status controller.
+ */
+struct status_controller_t {
+
+ /**
+ * Implements controller_t interface.
+ */
+ controller_t controller;
+};
+
+/**
+ * @brief Create a status_controller controller instance.
+ */
+controller_t *status_controller_create(context_t *context, void *param);
+
+#endif /* STATUS_CONTROLLER_H_ */
diff --git a/src/manager/database.c b/src/manager/database.c
new file mode 100644
index 000000000..5e8eb78f7
--- /dev/null
+++ b/src/manager/database.c
@@ -0,0 +1,195 @@
+/**
+ * @file database.c
+ *
+ * @brief Implementation of database_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "database.h"
+
+#include <sqlite3.h>
+#include <library.h>
+#include <enumerator.h>
+
+
+typedef struct private_database_t private_database_t;
+
+/**
+ * private data of database
+ */
+struct private_database_t {
+
+ /**
+ * public functions
+ */
+ database_t public;
+
+ /**
+ * SQLite database handle
+ */
+ sqlite3 *db;
+};
+
+/**
+ * database enumerator implements enumerator_t
+ */
+typedef struct {
+ enumerator_t enumerator;
+ sqlite3_stmt *stmt;
+} db_enumerator_t;
+
+/**
+ * destroy a database enumerator
+ */
+static void db_enumerator_destroy(db_enumerator_t* this)
+{
+ sqlite3_finalize(this->stmt);
+ free(this);
+}
+
+/**
+ * create a database enumerator
+ */
+static enumerator_t *db_enumerator_create(bool(*enumerate)(db_enumerator_t*,...),
+ sqlite3_stmt *stmt)
+{
+ db_enumerator_t *this = malloc_thing(db_enumerator_t);
+ this->enumerator.enumerate = (void*)enumerate;
+ this->enumerator.destroy = (void*)db_enumerator_destroy;
+ this->stmt = stmt;
+ return &this->enumerator;
+}
+
+/**
+ * enumerator function for empty enumerator
+ */
+static bool empty_enumerate(enumerator_t *enumerator, ...)
+{
+ return FALSE;
+}
+
+/**
+ * create an empty enumerator
+ */
+static enumerator_t* empty_enumerator_create()
+{
+ enumerator_t *this = malloc_thing(enumerator_t);
+ this->enumerate = empty_enumerate;
+ this->destroy = (void*)free;
+ return this;
+}
+
+/**
+ * Implementation of database_t.login.
+ */
+static int login(private_database_t *this, char *username, char *password)
+{
+ sqlite3_stmt *stmt;
+ int uid = 0;
+
+ if (sqlite3_prepare_v2(this->db,
+ "SELECT oid FROM users WHERE username = ? AND password = ?;",
+ -1, &stmt, NULL) == SQLITE_OK)
+ {
+ if (sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC) == SQLITE_OK &&
+ sqlite3_bind_text(stmt, 2, password, -1, SQLITE_STATIC) == SQLITE_OK &&
+ sqlite3_step(stmt) == SQLITE_ROW)
+ {
+ uid = sqlite3_column_int(stmt, 0);
+ }
+ sqlite3_finalize(stmt);
+ }
+ return uid;
+}
+
+/**
+ * enumerate function for gateway enumrator
+ */
+static bool gateway_enumerate(db_enumerator_t* e, ...)
+{
+ va_list args;
+ int *id, *port;
+ const char **name, **address;
+
+ va_start(args, e);
+ id = va_arg(args, typeof(id));
+ name = va_arg(args, typeof(name));
+ port = va_arg(args, typeof(port));
+ address = va_arg(args, typeof(address));
+ va_end(args);
+
+ if (sqlite3_step(e->stmt) == SQLITE_ROW)
+ {
+ *id = sqlite3_column_int(e->stmt, 0);
+ *name = sqlite3_column_text(e->stmt, 1);
+ *port = sqlite3_column_int(e->stmt, 2);
+ *address = sqlite3_column_text(e->stmt, 3);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of database_t.create_gateway_enumerator.
+ */
+static enumerator_t* create_gateway_enumerator(private_database_t *this, int user)
+{
+ sqlite3_stmt *stmt;
+
+ if (sqlite3_prepare_v2(this->db,
+ "SELECT gateways.oid AS gid, name, port, address FROM "
+ "gateways, user_gateway AS ug ON gid = ug.gateway WHERE ug.user = ?;",
+ -1, &stmt, NULL) == SQLITE_OK)
+ {
+ if (sqlite3_bind_int(stmt, 1, user) == SQLITE_OK)
+ {
+ return db_enumerator_create((void*)gateway_enumerate, stmt);
+ }
+ sqlite3_finalize(stmt);
+ }
+ return empty_enumerator_create();
+}
+
+/**
+ * Implementation of database_t.destroy
+ */
+static void destroy(private_database_t *this)
+{
+ sqlite3_close(this->db);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+database_t *database_create(char *dbfile)
+{
+ private_database_t *this = malloc_thing(private_database_t);
+
+ this->public.login = (int(*)(database_t*, char *username, char *password))login;
+ this->public.create_gateway_enumerator = (enumerator_t*(*)(database_t*,int))create_gateway_enumerator;
+ this->public.destroy = (void(*)(database_t*))destroy;
+
+ if (sqlite3_open(dbfile, &this->db) != SQLITE_OK)
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
diff --git a/src/manager/database.h b/src/manager/database.h
new file mode 100644
index 000000000..7edcde4fa
--- /dev/null
+++ b/src/manager/database.h
@@ -0,0 +1,69 @@
+/**
+ * @file database.h
+ *
+ * @brief Interface of database_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef DATABASE_H_
+#define DATABASE_H_
+
+#include <enumerator.h>
+
+
+typedef struct database_t database_t;
+
+/**
+ * @brief Persistent database.
+ */
+struct database_t {
+
+ /**
+ * @brief Try to log in using specified credentials.
+ *
+ * @param username username
+ * @param password plaintext password
+ * @return user ID if login good, 0 otherwise
+ */
+ int (*login)(database_t *this, char *username, char *password);
+
+ /**
+ * @brief Create an iterator over the gateways.
+ *
+ * enumerate() arguments: int id, char *name, int port, char *address
+ * If port is 0, address is a Unix socket address.
+ *
+ * @param user user Id
+ * @return enumerator
+ */
+ enumerator_t* (*create_gateway_enumerator)(database_t *this, int user);
+
+ /**
+ * @brief Destroy a database instance.
+ */
+ void (*destroy)(database_t *this);
+};
+
+/**
+ * @brief Create a database instance.
+ *
+ * @param dbfile SQLite database file
+ */
+database_t *database_create(char *dbfile);
+
+#endif /* DATABASE_H_ */
diff --git a/src/manager/gateway.c b/src/manager/gateway.c
new file mode 100644
index 000000000..b918da26d
--- /dev/null
+++ b/src/manager/gateway.c
@@ -0,0 +1,153 @@
+/**
+ * @file gateway.c
+ *
+ * @brief Implementation of gateway_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "gateway.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <string.h>
+
+typedef struct private_gateway_t private_gateway_t;
+
+/**
+ * private data of gateway
+ */
+struct private_gateway_t {
+
+ /**
+ * public functions
+ */
+ gateway_t public;
+
+ /**
+ * name of the gateway
+ */
+ char *name;
+
+ /**
+ * connection information
+ */
+ host_t *host;
+
+ /**
+ * socket file descriptor, > 0 if connected
+ */
+ int fd;
+};
+
+/**
+ * establish connection to gateway
+ */
+static bool connect_(private_gateway_t *this)
+{
+ if (this->fd >= 0)
+ {
+ close(this->fd);
+ }
+ this->fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (this->fd < 0)
+ {
+ return FALSE;
+ }
+ if (connect(this->fd, this->host->get_sockaddr(this->host),
+ *this->host->get_sockaddr_len(this->host)) != 0)
+ {
+ close(this->fd);
+ this->fd = -1;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/**
+ * Implementation of gateway_t.request.
+ */
+static char* request(private_gateway_t *this, char *xml)
+{
+ if (this->fd < 0)
+ {
+ if (!connect_(this))
+ {
+ return NULL;
+ }
+ }
+ while (TRUE)
+ {
+ char buf[8096];
+ ssize_t len;
+
+ len = strlen(xml);
+ if (send(this->fd, xml, len, 0) != len)
+ {
+ return NULL;
+ }
+ len = recv(this->fd, buf, sizeof(buf) - 1, 0);
+ if (len < 0)
+ {
+ return NULL;
+ }
+ if (len == 0)
+ {
+ if (!connect_(this))
+ {
+ return NULL;
+ }
+ continue;
+ }
+ buf[len] = 0;
+ return strdup(buf);
+ }
+}
+
+/**
+ * Implementation of gateway_t.destroy
+ */
+static void destroy(private_gateway_t *this)
+{
+ if (this->fd >= 0)
+ {
+ close(this->fd);
+ }
+ this->host->destroy(this->host);
+ free(this->name);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+gateway_t *gateway_create(char *name, host_t *host)
+{
+ private_gateway_t *this = malloc_thing(private_gateway_t);
+
+ this->public.request = (char*(*)(gateway_t*, char *xml))request;
+ this->public.destroy = (void(*)(gateway_t*))destroy;
+
+ this->name = strdup(name);
+ this->host = host;
+ this->fd = -1;
+
+ return &this->public;
+}
+
diff --git a/src/manager/gateway.h b/src/manager/gateway.h
new file mode 100644
index 000000000..7b5d91045
--- /dev/null
+++ b/src/manager/gateway.h
@@ -0,0 +1,58 @@
+/**
+ * @file gateway.h
+ *
+ * @brief Interface of gateway_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef GATEWAY_H_
+#define GATEWAY_H_
+
+#include <utils/host.h>
+
+typedef struct gateway_t gateway_t;
+
+/**
+ * @brief A connection to a gateway.
+ */
+struct gateway_t {
+
+ /**
+ * @brief Send an XML request to the gateway.
+ *
+ * @param xml xml request string
+ * @return allocated xml response string
+ */
+ char* (*request)(gateway_t *this, char *xml);
+
+ /**
+ * @brief Destroy a gateway instance.
+ */
+ void (*destroy)(gateway_t *this);
+};
+
+/**
+ * @brief Create a gateway instance.
+ *
+ * @param name name of the gateway
+ * @param host gateway connection endpoint
+ * @param
+ */
+gateway_t *gateway_create(char *name, host_t *host);
+
+#endif /* GATEWAY_H_ */
diff --git a/src/manager/lib/context.h b/src/manager/lib/context.h
new file mode 100644
index 000000000..23c979b8e
--- /dev/null
+++ b/src/manager/lib/context.h
@@ -0,0 +1,47 @@
+/**
+ * @file context.h
+ *
+ * @brief Interface of context_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef CONTEXT_H_
+#define CONTEXT_H_
+
+typedef struct context_t context_t;
+
+/**
+ * @brief Constructor function for a context
+ */
+typedef context_t *(*context_constructor_t)(void *param);
+
+/**
+ * @brief Custom session context
+ *
+ */
+struct context_t {
+
+ /**
+ * @brief Destroy the context_t.
+ *
+ * @param this calling object
+ */
+ void (*destroy) (context_t *this);
+};
+
+#endif /* CONTEXT_H_ */
diff --git a/src/manager/lib/controller.h b/src/manager/lib/controller.h
new file mode 100644
index 000000000..92968d8a6
--- /dev/null
+++ b/src/manager/lib/controller.h
@@ -0,0 +1,75 @@
+/**
+ * @file controller.h
+ *
+ * @brief Interface controller_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef CONTROLLER_H_
+#define CONTROLLER_H_
+
+#include "request.h"
+#include "response.h"
+#include "context.h"
+
+typedef struct controller_t controller_t;
+
+/**
+ * @brief Controller action handle function
+ *
+ * @param request http request
+ * @param response http response
+ */
+typedef void *(*controller_handler_t)(controller_t *this, request_t *request, response_t *response);
+
+/**
+ * @brief Constructor function for a controller
+ *
+ * @param context session specific context
+ * @param param user supplied param
+ */
+typedef controller_t *(*controller_constructor_t)(context_t* context, void *param);
+
+/**
+ * @brief Controller interface, to be implemented by users controllers.
+ *
+ */
+struct controller_t {
+
+ /**
+ * @brief Get the name of the controller.
+ *
+ * @return name of the controller
+ */
+ char* (*get_name)(controller_t *this);
+
+ /**
+ * @brief Get the controllers handler function for an action name.
+ *
+ * @param name name of the action
+ * @return controllers handler
+ */
+ controller_handler_t (*get_handler)(controller_t *this, char *name);
+
+ /**
+ * @brief Destroy the controller instance.
+ */
+ void (*destroy) (controller_t *this);
+};
+
+#endif /* CONTROLLER_H_ */
diff --git a/src/manager/lib/dispatcher.c b/src/manager/lib/dispatcher.c
new file mode 100644
index 000000000..018122e6f
--- /dev/null
+++ b/src/manager/lib/dispatcher.c
@@ -0,0 +1,348 @@
+/**
+ * @file dispatcher.c
+ *
+ * @brief Implementation of dispatcher_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "dispatcher.h"
+
+#include "request.h"
+#include "session.h"
+
+#include <fcgiapp.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <utils/linked_list.h>
+
+typedef struct private_dispatcher_t private_dispatcher_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_dispatcher_t {
+
+ /**
+ * public functions
+ */
+ dispatcher_t public;
+
+ /**
+ * fcgi socket fd
+ */
+ int fd;
+
+ /**
+ * thread list
+ */
+ pthread_t *threads;
+
+ /**
+ * number of threads in "threads"
+ */
+ int thread_count;
+
+ /**
+ * session locking mutex
+ */
+ pthread_mutex_t mutex;
+
+ /**
+ * List of sessions
+ */
+ linked_list_t *sessions;
+
+ /**
+ * session timeout
+ */
+ time_t timeout;
+
+ /**
+ * List of controllers controller_constructor_t
+ */
+ linked_list_t *controllers;
+
+ /**
+ * constructor function to create session context (in constructor_entry_t)
+ */
+ context_constructor_t context_constructor;
+
+ /**
+ * user param to context constructor
+ */
+ void *param;
+};
+
+typedef struct {
+ /** constructor function */
+ controller_constructor_t constructor;
+ /** parameter to constructor */
+ void *param;
+} constructor_entry_t;
+
+typedef struct {
+ /** session instance */
+ session_t *session;
+ /** condvar to wait for session */
+ pthread_cond_t cond;
+ /** number of threads waiting for session */
+ int waiting;
+ /** last use of the session */
+ time_t used;
+} session_entry_t;
+
+/**
+ * create a session and instanciate controllers
+ */
+static session_t* load_session(private_dispatcher_t *this)
+{
+ iterator_t *iterator;
+ constructor_entry_t *entry;
+ session_t *session;
+ context_t *context = NULL;
+ controller_t *controller;
+
+ if (this->context_constructor)
+ {
+ context = this->context_constructor(this->param);
+ }
+ session = session_create(context);
+
+ iterator = this->controllers->create_iterator(this->controllers, TRUE);
+ while (iterator->iterate(iterator, (void**)&entry))
+ {
+ controller = entry->constructor(context, entry->param);
+ session->add_controller(session, controller);
+ }
+ iterator->destroy(iterator);
+
+ return session;
+}
+
+/**
+ * create a new session entry
+ */
+static session_entry_t *session_entry_create(private_dispatcher_t *this)
+{
+ session_entry_t *entry;
+
+ entry = malloc_thing(session_entry_t);
+ entry->waiting = 1;
+ pthread_cond_init(&entry->cond, NULL);
+ entry->session = load_session(this);
+
+ return entry;
+}
+
+static void session_entry_destroy(session_entry_t *entry)
+{
+ entry->session->destroy(entry->session);
+ free(entry);
+}
+
+/**
+ * Implementation of dispatcher_t.add_controller.
+ */
+static void add_controller(private_dispatcher_t *this,
+ controller_constructor_t constructor, void *param)
+{
+ constructor_entry_t *entry = malloc_thing(constructor_entry_t);
+
+ entry->constructor = constructor;
+ entry->param = param;
+ this->controllers->insert_last(this->controllers, entry);
+}
+
+/**
+ * Dispatch
+ */
+static void dispatch(private_dispatcher_t *this)
+{
+ FCGX_Request fcgi_req;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ if (FCGX_InitRequest(&fcgi_req, this->fd, 0) == 0)
+ {
+ while (TRUE)
+ {
+ request_t *request;
+ response_t *response;
+ session_entry_t *current, *found = NULL;
+ iterator_t *iterator;
+ time_t now;
+ char *sid;
+ int accepted;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ accepted = FCGX_Accept_r(&fcgi_req);
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
+ if (accepted != 0)
+ {
+ break;
+ }
+
+ /* prepare */
+ response = response_create(&fcgi_req);
+ request = request_create(&fcgi_req);
+ sid = request->get_cookie(request, "SID");
+ now = time(NULL);
+
+ /* find session */
+ iterator = this->sessions->create_iterator_locked(this->sessions, &this->mutex);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (sid && streq(current->session->get_sid(current->session), sid))
+ {
+ found = current;
+ found->waiting++;
+ }
+ else if (current->waiting == 0 &&
+ current->used + this->timeout > now)
+ {
+ iterator->remove(iterator);
+ session_entry_destroy(current);
+ }
+ }
+ iterator->destroy(iterator);
+
+ if (found)
+ { /* wait until session is unused */
+ pthread_mutex_lock(&this->mutex);
+ while (found->waiting > 1)
+ {
+ pthread_cond_wait(&found->cond, &this->mutex);
+ }
+ pthread_mutex_unlock(&this->mutex);
+ }
+ else
+ { /* create a new session if not found */
+ found = session_entry_create(this);
+ pthread_mutex_lock(&this->mutex);
+ this->sessions->insert_first(this->sessions, found);
+ pthread_mutex_unlock(&this->mutex);
+ }
+
+ /* start processing */
+ found->session->process(found->session, request, response);
+ found->used = time(NULL);
+
+ /* release session */
+ pthread_mutex_lock(&this->mutex);
+ found->waiting--;
+ pthread_cond_signal(&found->cond);
+ pthread_mutex_unlock(&this->mutex);
+
+ /* cleanup */
+ request->destroy(request);
+ response->destroy(response);
+
+ /*
+ FCGX_FPrintF(fcgi_req.out, "<ul>");
+ char **env = fcgi_req.envp;
+ while (*env)
+ {
+ FCGX_FPrintF(fcgi_req.out, "<li>%s</li>", *env);
+ env++;
+ }
+ FCGX_FPrintF(fcgi_req.out, "</ul>");
+ */
+ }
+ }
+}
+
+/**
+ * Implementation of dispatcher_t.run.
+ */
+static void run(private_dispatcher_t *this, int threads)
+{
+ this->thread_count = threads;
+ this->threads = malloc(sizeof(pthread_t) * threads);
+ while (threads)
+ {
+ if (pthread_create(&this->threads[threads - 1],
+ NULL, (void*)dispatch, this) == 0)
+ {
+ threads--;
+ }
+ }
+}
+
+/**
+ * Implementation of dispatcher_t.waitsignal.
+ */
+static void waitsignal(private_dispatcher_t *this)
+{
+ sigset_t set;
+ int sig;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGTERM);
+ sigaddset(&set, SIGHUP);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+ sigwait(&set, &sig);
+}
+
+/**
+ * Implementation of dispatcher_t.destroy
+ */
+static void destroy(private_dispatcher_t *this)
+{
+ FCGX_ShutdownPending();
+ while (this->thread_count--)
+ {
+ pthread_cancel(this->threads[this->thread_count]);
+ pthread_join(this->threads[this->thread_count], NULL);
+ }
+ this->sessions->destroy_function(this->sessions, (void*)session_entry_destroy);
+ this->controllers->destroy_function(this->controllers, free);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+dispatcher_t *dispatcher_create(context_constructor_t constructor, void *param)
+{
+ private_dispatcher_t *this = malloc_thing(private_dispatcher_t);
+
+ this->public.add_controller = (void(*)(dispatcher_t*, controller_constructor_t, void*))add_controller;
+ this->public.run = (void(*)(dispatcher_t*, int threads))run;
+ this->public.waitsignal = (void(*)(dispatcher_t*))waitsignal;
+ this->public.destroy = (void(*)(dispatcher_t*))destroy;
+
+ this->sessions = linked_list_create();
+ this->controllers = linked_list_create();
+ this->context_constructor = constructor;
+ pthread_mutex_init(&this->mutex, NULL);
+ this->param = param;
+ this->fd = 0;
+ this->timeout = 180;
+
+ FCGX_Init();
+
+#ifdef FCGI_SOCKET
+ unlink(FCGI_SOCKET);
+ this->fd = FCGX_OpenSocket(FCGI_SOCKET, 10);
+#endif /* FCGI_SOCKET */
+
+ return &this->public;
+}
+
diff --git a/src/manager/lib/dispatcher.h b/src/manager/lib/dispatcher.h
new file mode 100644
index 000000000..5119a1eab
--- /dev/null
+++ b/src/manager/lib/dispatcher.h
@@ -0,0 +1,78 @@
+/**
+ * @file dispatcher.h
+ *
+ * @brief Interface of dispatcher_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef DISPATCHER_H_
+#define DISPATCHER_H_
+
+#include "controller.h"
+
+typedef struct dispatcher_t dispatcher_t;
+
+/**
+ * @brief Dispatcher, accepts connections using multiple threads.
+ *
+ * The dispatcher creates a session for each client (using SID cookies). In
+ * each session, a session context is created using the context constructor.
+ * Each controller is instanciated in the session using the controller
+ * constructor added with add_controller.
+ */
+struct dispatcher_t {
+
+ /**
+ * @brief Register a controller to the dispatcher.
+ *
+ * @param constructor constructor function to the conntroller
+ * @param param param to pass to constructor
+ */
+ void (*add_controller)(dispatcher_t *this,
+ controller_constructor_t constructor, void *param);
+
+ /**
+ * @brief Start with dispatching.
+ *
+ * @param thread number of dispatching threads
+ */
+ void (*run)(dispatcher_t *this, int threads);
+
+ /**
+ * @brief Wait for a relevant signal action.
+ */
+ void (*waitsignal)(dispatcher_t *this);
+
+ /**
+ * @brief Destroy the dispatcher_t.
+ */
+ void (*destroy) (dispatcher_t *this);
+};
+
+/**
+ * @brief Create a dispatcher.
+ *
+ * The context constructor is invoked to create a session context for
+ * each session.
+ *
+ * @param constructor construction function for session context
+ * @param param parameter to supply to context constructor
+ */
+dispatcher_t *dispatcher_create(context_constructor_t constructor, void *param);
+
+#endif /* DISPATCHER_H_ */
diff --git a/src/manager/lib/enumerator.h b/src/manager/lib/enumerator.h
new file mode 100644
index 000000000..de272f9c9
--- /dev/null
+++ b/src/manager/lib/enumerator.h
@@ -0,0 +1,49 @@
+/**
+ * @file enumerator.h
+ *
+ * @brief Interface of enumerator_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef ENUMERATOR_H_
+#define ENUMERATOR_H_
+
+#include <library.h>
+
+typedef struct enumerator_t enumerator_t;
+
+/**
+ * @brief Enumerate is simpler, but more flexible than iterator.
+ */
+struct enumerator_t {
+
+ /**
+ * @brief Enumerate collection.
+ *
+ * @param ... variable argument list of pointers, NULL terminated
+ * @return TRUE if pointers returned
+ */
+ bool (*enumerate)(enumerator_t *this, ...);
+
+ /**
+ * @brief Destroy a enumerator instance.
+ */
+ void (*destroy)(enumerator_t *this);
+};
+
+#endif /* ENUMERATOR_H_ */
diff --git a/src/manager/lib/request.c b/src/manager/lib/request.c
new file mode 100644
index 000000000..2e12d3643
--- /dev/null
+++ b/src/manager/lib/request.c
@@ -0,0 +1,306 @@
+/**
+ * @file request.c
+ *
+ * @brief Implementation of request_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include "request.h"
+
+#include <stdlib.h>
+
+#include <utils/linked_list.h>
+
+typedef struct {
+ char *name;
+ char *value;
+} name_value_t;
+
+/**
+ * destroy a name value pair
+ */
+static void name_value_destroy(name_value_t *this)
+{
+ free(this->name);
+ free(this->value);
+ free(this);
+}
+
+typedef struct private_request_t private_request_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_request_t {
+
+ /**
+ * public functions
+ */
+ request_t public;
+
+ /**
+ * the associated fcgi request
+ */
+ FCGX_Request *req;
+
+ /**
+ * list of cookies (name_value_t)
+ */
+ linked_list_t *cookies;
+
+ /**
+ * list of post data (name_value_t)
+ */
+ linked_list_t *posts;
+};
+
+/**
+ * Implementation of request_t.get_cookie.
+ */
+static char* get_cookie(private_request_t *this, char *name)
+{
+ char *value = NULL;
+ name_value_t *cookie;
+ iterator_t *iterator;
+
+ iterator = this->cookies->create_iterator(this->cookies, TRUE);
+ while (iterator->iterate(iterator, (void**)&cookie))
+ {
+ if (streq(cookie->name, name))
+ {
+ value = cookie->value;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ return value;
+}
+
+/**
+ * Implementation of request_t.get_path.
+ */
+static char* get_path(private_request_t *this)
+{
+ char * path = FCGX_GetParam("PATH_INFO", this->req->envp);
+ return path ? path : "";
+}
+
+/**
+ * Implementation of request_t.get_post_data.
+ */
+static char* get_post_data(private_request_t *this, char *name)
+{
+ char *value = NULL;
+ name_value_t *data;
+ iterator_t *iterator;
+
+ iterator = this->posts->create_iterator(this->posts, TRUE);
+ while (iterator->iterate(iterator, (void**)&data))
+ {
+ if (streq(data->name, name))
+ {
+ value = data->value;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ return value;
+}
+
+/**
+ * convert 2 digit hex string to a integer
+ */
+static char hex2char(char *hex)
+{
+ static char hexdig[] = "00112233445566778899AaBbCcDdEeFf";
+
+ return (strchr(hexdig, hex[1]) - hexdig)/2 +
+ ((strchr(hexdig, hex[0]) - hexdig)/2 * 16);
+}
+
+/**
+ * unescape a string up to the delimiter, and return a clone
+ */
+static char *unescape(char **pos, char delimiter)
+{
+ char *ptr, *res, *end, code[3] = {'\0','\0','\0'};
+
+ if (**pos == '\0')
+ {
+ return NULL;
+ }
+ ptr = strchr(*pos, delimiter);
+ if (ptr)
+ {
+ res = strndup(*pos, ptr - *pos);
+ *pos = ptr + 1;
+ }
+ else
+ {
+ res = strdup(*pos);
+ *pos = "";
+ }
+ end = res + strlen(res) + 1;
+ /* replace '+' with ' ' */
+ ptr = res;
+ while ((ptr = strchr(ptr, '+')))
+ {
+ *ptr = ' ';
+ }
+ /* replace %HH with its ascii value */
+ ptr = res;
+ while ((ptr = strchr(ptr, '%')))
+ {
+ if (ptr > end - 2)
+ {
+ break;
+ }
+ strncpy(code, ptr + 1, 2);
+ *ptr = hex2char(code);
+ memmove(ptr + 1, ptr + 3, end - (ptr + 3));
+ }
+ return res;
+}
+
+/**
+ * parse the http POST data
+ */
+static void parse_post(private_request_t *this)
+{
+ char buf[4096], *pos, *name, *value;
+ name_value_t *data;
+ int len;
+
+ if (!streq(FCGX_GetParam("REQUEST_METHOD", this->req->envp), "POST") ||
+ !streq(FCGX_GetParam("CONTENT_TYPE", this->req->envp),
+ "application/x-www-form-urlencoded"))
+ {
+ return;
+ }
+
+ len = FCGX_GetStr(buf, sizeof(buf) - 1, this->req->in);
+ if (len != atoi(FCGX_GetParam("CONTENT_LENGTH", this->req->envp)))
+ {
+ return;
+ }
+ buf[len] = 0;
+
+ pos = buf;
+ while (TRUE)
+ {
+ name = unescape(&pos, '=');
+ if (name)
+ {
+ value = unescape(&pos, '&');
+ if (value)
+ {
+ data = malloc_thing(name_value_t);
+ data->name = name;
+ data->value = value;
+ this->posts->insert_last(this->posts, data);
+ continue;
+ }
+ else
+ {
+ free(name);
+ }
+ }
+ break;
+ }
+}
+
+/**
+ * parse the requests cookies
+ */
+static void parse_cookies(private_request_t *this)
+{
+ char *str, *pos;
+ name_value_t *cookie;
+
+ str = FCGX_GetParam("HTTP_COOKIE", this->req->envp);
+ while (str)
+ {
+ if (*str == ' ')
+ {
+ str++;
+ continue;
+ }
+ pos = strchr(str, '=');
+ if (pos == NULL)
+ {
+ break;
+ }
+ cookie = malloc_thing(name_value_t);
+ cookie->name = strndup(str, pos - str);
+ cookie->value = NULL;
+ str = pos + 1;
+ if (str)
+ {
+ pos = strchr(str, ';');
+ if (pos)
+ {
+ cookie->value = strndup(str, pos - str);
+ }
+ else
+ {
+ cookie->value = strdup(str);
+ }
+ }
+ this->cookies->insert_last(this->cookies, cookie);
+ if (pos == NULL)
+ {
+ break;
+ }
+ str = pos + 1;
+ }
+}
+
+/**
+ * Implementation of request_t.destroy
+ */
+static void destroy(private_request_t *this)
+{
+ this->cookies->destroy_function(this->cookies, (void*)name_value_destroy);
+ this->posts->destroy_function(this->posts, (void*)name_value_destroy);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+request_t *request_create(FCGX_Request *request)
+{
+ private_request_t *this = malloc_thing(private_request_t);
+
+ this->public.get_path = (char*(*)(request_t*))get_path;
+ this->public.get_cookie = (char*(*)(request_t*,char*))get_cookie;
+ this->public.get_post_data = (char*(*)(request_t*, char *name))get_post_data;
+ this->public.destroy = (void(*)(request_t*))destroy;
+
+ this->req = request;
+ this->cookies = linked_list_create();
+ this->posts = linked_list_create();
+
+ parse_cookies(this);
+ parse_post(this);
+
+ return &this->public;
+}
+
diff --git a/src/manager/lib/request.h b/src/manager/lib/request.h
new file mode 100644
index 000000000..852238a1d
--- /dev/null
+++ b/src/manager/lib/request.h
@@ -0,0 +1,73 @@
+/**
+ * @file request.h
+ *
+ * @brief Interface of request_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef REQUEST_H_
+#define REQUEST_H_
+
+
+#include <fcgiapp.h>
+
+typedef struct request_t request_t;
+
+/**
+ * @brief A HTTP request, encapsulates FCGX_Request.
+ *
+ */
+struct request_t {
+
+ /**
+ * @brief Get a cookie the client sent in the request.
+ *
+ * @param name name of the cookie
+ * @return cookie value, NULL if no such cookie found
+ */
+ char* (*get_cookie)(request_t *this, char *name);
+
+ /**
+ * @brief Get the request path relative to the application.
+ *
+ * @return path
+ */
+ char* (*get_path)(request_t *this);
+
+ /**
+ * @brief Get a post variable included in the request.
+ *
+ * @param name name of the POST variable
+ * @return value, NULL if not found
+ */
+ char* (*get_post_data)(request_t *this, char *name);
+
+ /**
+ * @brief Destroy the request_t.
+ */
+ void (*destroy) (request_t *this);
+};
+
+/**
+ * @brief Create a request from the fastcgi struct.
+ *
+ * @param request the FCGI request
+ */
+request_t *request_create(FCGX_Request *request);
+
+#endif /* REQUEST_H_ */
diff --git a/src/manager/lib/response.c b/src/manager/lib/response.c
new file mode 100644
index 000000000..ae74ab6e5
--- /dev/null
+++ b/src/manager/lib/response.c
@@ -0,0 +1,223 @@
+/**
+ * @file response.c
+ *
+ * @brief Implementation of response_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "response.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <utils/linked_list.h>
+
+typedef struct {
+ char *name;
+ char *value;
+} name_value_t;
+
+/**
+ * create name value pair
+ */
+static name_value_t *name_value_create(char *name, char *value)
+{
+ name_value_t *this = malloc_thing(name_value_t);
+
+ this->name = strdup(name);
+ this->value = strdup(value);
+
+ return this;
+}
+
+/**
+ * destroy a name value pair
+ */
+static void name_value_destroy(name_value_t *this)
+{
+ free(this->name);
+ free(this->value);
+ free(this);
+}
+
+typedef struct private_response_t private_response_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_response_t {
+
+ /**
+ * public functions
+ */
+ response_t public;
+
+ /**
+ * the associated fcgi request
+ */
+ FCGX_Request *req;
+
+ /**
+ * Content type
+ */
+ char *content_type;
+
+ /**
+ * list of cookies (name_value_t)
+ */
+ linked_list_t *cookies;
+
+ /**
+ * list of custom headers (name_value_t)
+ */
+ linked_list_t *headers;
+
+ /**
+ * headers already written?
+ */
+ bool started;
+};
+
+/**
+ * write the headers, if not already written
+ */
+static void write_headers(private_response_t *this)
+{
+ iterator_t *iterator;
+ name_value_t *current;
+
+ FCGX_FPrintF(this->req->out, "Content-type: %s\n", this->content_type);
+ iterator = this->cookies->create_iterator(this->cookies, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ FCGX_FPrintF(this->req->out, "Set-Cookie: %s=%s; path=%s\n",
+ current->name, current->value,
+ FCGX_GetParam("SCRIPT_NAME", this->req->envp));
+ }
+ iterator->destroy(iterator);
+ iterator = this->cookies->create_iterator(this->headers, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ FCGX_FPrintF(this->req->out, "%s: %s\n",
+ current->name, current->value);
+ }
+ iterator->destroy(iterator);
+ FCGX_PutChar('\n', this->req->out);
+ this->started = TRUE;
+}
+
+/**
+ * Implementation of response_t.print.
+ */
+static void print_(private_response_t *this, char *str)
+{
+ if (!this->started)
+ {
+ write_headers(this);
+ }
+ FCGX_PutS(str, this->req->out);
+}
+
+/**
+ * Implementation of response_t.printf.
+ */
+static void printf_(private_response_t *this, char *format, ...)
+{
+ va_list args;
+
+ if (!this->started)
+ {
+ write_headers(this);
+ }
+
+ va_start(args, format);
+ FCGX_VFPrintF(this->req->out, format, args);
+ va_end(args);
+}
+
+/**
+ * Implementation of response_t.add_header.
+ */
+static void add_header(private_response_t *this, char *name, char *value)
+{
+ this->headers->insert_last(this->headers, name_value_create(name, value));
+}
+
+/**
+ * Implementation of response_t.set_content_type.
+ */
+static void set_content_type(private_response_t *this, char *type)
+{
+ free(this->content_type);
+ this->content_type = strdup(type);
+}
+
+/**
+ * Implementation of response_t.add_cookie.
+ */
+static void add_cookie(private_response_t *this, char *name, char *value)
+{
+ this->cookies->insert_last(this->cookies, name_value_create(name, value));
+}
+
+/**
+ * Implementation of response_t.redirect.
+ */
+static void redirect(private_response_t *this, char *location)
+{
+ FCGX_FPrintF(this->req->out, "Status: 303 See Other\n");
+ FCGX_FPrintF(this->req->out, "Location: %s%s%s\n\n",
+ FCGX_GetParam("SCRIPT_NAME", this->req->envp),
+ *location == '/' ? "" : "/", location);
+}
+
+/**
+ * Implementation of response_t.destroy
+ */
+static void destroy(private_response_t *this)
+{
+ this->headers->destroy_function(this->headers, (void*)name_value_destroy);
+ this->cookies->destroy_function(this->cookies, (void*)name_value_destroy);
+ free(this->content_type);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+response_t *response_create(FCGX_Request *request)
+{
+ private_response_t *this = malloc_thing(private_response_t);
+
+ this->public.print = (void(*)(response_t*, char *str))print_;
+ this->public.printf = (void(*)(response_t*, char *format, ...))printf_;
+ this->public.add_header = (void(*)(response_t*, char *name, char *value))add_header;
+ this->public.set_content_type = (void(*)(response_t*, char *type))set_content_type;
+ this->public.add_cookie = (void(*)(response_t*, char *name, char *value))add_cookie;
+ this->public.redirect = (void(*)(response_t*, char *location))redirect;
+ this->public.destroy = (void(*)(response_t*))destroy;
+
+ this->req = request;
+ this->headers = linked_list_create();
+ this->cookies = linked_list_create();
+ this->content_type = strdup("text/html");
+ this->started = FALSE;
+
+ return &this->public;
+}
+
diff --git a/src/manager/lib/response.h b/src/manager/lib/response.h
new file mode 100644
index 000000000..e3be2cf43
--- /dev/null
+++ b/src/manager/lib/response.h
@@ -0,0 +1,95 @@
+/**
+ * @file response.h
+ *
+ * @brief Interface of response_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef RESPONSE_H_
+#define RESPONSE_H_
+
+
+#include <fcgiapp.h>
+
+typedef struct response_t response_t;
+
+/**
+ * @brief A HTTP response, wraps response functionality around FCGX_Request.
+ *
+ */
+struct response_t {
+
+ /**
+ * @brief Write a string to the client.
+ *
+ * @param str string to write
+ */
+ void (*print)(response_t *this, char *str);
+
+ /**
+ * @brief Write a printf like format string to client.
+ *
+ * @param format printf like format string
+ * @param ... variable argument list
+ */
+ void (*printf)(response_t *this, char *format, ...);
+
+ /**
+ * @brief Add a custom header to the response.
+ *
+ * @param name name of the header
+ * @param value value of the header
+ */
+ void (*add_header)(response_t *this, char *name, char *value);
+
+ /**
+ * @brief Set the content type (Content-Type header).
+ *
+ * @param type content type (e.g. text/html)
+ */
+ void (*set_content_type)(response_t *this, char *type);
+
+ /**
+ * @brief Add a cookie to the response (Set-Cookie header).
+ *
+ * @param name name of the cookie to set
+ * @param value value of the cookie
+ */
+ void (*add_cookie)(response_t *this, char *name, char *value);
+
+ /**
+ * @brief Redirect the client to another location.
+ *
+ * @param location location to redirect to
+ */
+ void (*redirect)(response_t *this, char *location);
+
+ /**
+ * @brief Destroy a response_t.
+ */
+ void (*destroy) (response_t *this);
+};
+
+/**
+ * @brief Create a response.
+ *
+ * @param request the FCGI request structure
+ */
+response_t *response_create(FCGX_Request *request);
+
+#endif /* RESPONSE_H_ */
diff --git a/src/manager/lib/session.c b/src/manager/lib/session.c
new file mode 100644
index 000000000..be25f2737
--- /dev/null
+++ b/src/manager/lib/session.c
@@ -0,0 +1,185 @@
+/**
+ * @file session.c
+ *
+ * @brief Implementation of session_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include "session.h"
+
+#include <string.h>
+#include <fcgiapp.h>
+#include <stdio.h>
+
+#include <utils/linked_list.h>
+#include <utils/randomizer.h>
+
+typedef struct private_session_t private_session_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_session_t {
+
+ /**
+ * public functions
+ */
+ session_t public;
+
+ /**
+ * session ID
+ */
+ char *sid;
+
+ /**
+ * list of controller instances controller_t
+ */
+ linked_list_t *controllers;
+
+ /**
+ * user defined session context
+ */
+ context_t *context;
+};
+
+/**
+ * Implementation of session_t.load_controller.
+ */
+static void add_controller(private_session_t *this, controller_t *controller)
+{
+ this->controllers->insert_last(this->controllers, controller);
+}
+
+/**
+ * Create a session ID and a cookie
+ */
+static void create_sid(private_session_t *this, response_t *response)
+{
+ char buf[16];
+ chunk_t chunk = chunk_from_buf(buf);
+ randomizer_t *randomizer = randomizer_create();
+
+ randomizer->get_pseudo_random_bytes(randomizer, sizeof(buf), buf);
+ asprintf(&this->sid, "%#B", &chunk);
+ response->add_cookie(response, "SID", this->sid);
+ randomizer->destroy(randomizer);
+}
+
+/**
+ * Implementation of session_t.process.
+ */
+static void process(private_session_t *this,
+ request_t *request, response_t *response)
+{
+ char *pos, *path, *controller, *action;
+ iterator_t *iterator;
+ bool handled = FALSE;
+ controller_handler_t handler;
+ controller_t *current;
+
+ if (this->sid == NULL)
+ {
+ create_sid(this, response);
+ }
+
+ path = request->get_path(request);
+ if (*path == '/') path++;
+ pos = strchr(path, '/');
+ if (pos == NULL)
+ {
+ controller = strdup(path);
+ action = strdup("");
+ }
+ else
+ {
+ controller = strndup(path, pos - path);
+ path = pos + 1;
+ pos = strchr(path, '/');
+ if (pos == NULL)
+ {
+ action = strdup(path);
+ }
+ else
+ {
+ action = strndup(path, pos - path);
+ }
+ }
+ iterator = this->controllers->create_iterator(this->controllers, TRUE);
+ while (iterator->iterate(iterator, (void**)&current))
+ {
+ if (streq(current->get_name(current), controller))
+ {
+ handler = current->get_handler(current, action);
+ if (handler)
+ {
+ handler(current, request, response);
+ handled = TRUE;
+ }
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ free(controller);
+ free(action);
+ if (!handled)
+ {
+ response->add_header(response, "Status", "400 Not Found");
+ response->printf(response, "<html><body><h1>Not Found</h1></body></html>\n");
+ }
+}
+
+/**
+ * Implementation of session_t.get_sid.
+ */
+static char* get_sid(private_session_t *this)
+{
+ return this->sid;
+}
+
+/**
+ * Implementation of session_t.destroy
+ */
+static void destroy(private_session_t *this)
+{
+ this->controllers->destroy_offset(this->controllers, offsetof(controller_t, destroy));
+ if (this->context) this->context->destroy(this->context);
+ free(this->sid);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+session_t *session_create(context_t *context)
+{
+ private_session_t *this = malloc_thing(private_session_t);
+
+ this->public.add_controller = (void(*)(session_t*, controller_t*))add_controller;
+ this->public.process = (void(*)(session_t*, request_t*,response_t*))process;
+ this->public.get_sid = (char*(*)(session_t*))get_sid;
+ this->public.destroy = (void(*)(session_t*))destroy;
+
+ this->sid = NULL;
+ this->controllers = linked_list_create();
+ this->context = context;
+
+ return &this->public;
+}
+
diff --git a/src/manager/lib/session.h b/src/manager/lib/session.h
new file mode 100644
index 000000000..baaacd098
--- /dev/null
+++ b/src/manager/lib/session.h
@@ -0,0 +1,75 @@
+/**
+ * @file session.h
+ *
+ * @brief Interface of session_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef SESSION_H_
+#define SESSION_H_
+
+#include "request.h"
+#include "response.h"
+#include "controller.h"
+
+typedef struct session_t session_t;
+
+/**
+ * @brief A session, identified by a session ID.
+ *
+ */
+struct session_t {
+
+ /**
+ * @brief Get the session ID of the session.
+ *
+ * @return session ID
+ */
+ char* (*get_sid)(session_t *this);
+
+ /**
+ * @brief Add a controller instance to the session.
+ *
+ * @param controller controller to add
+ */
+ void (*add_controller)(session_t *this, controller_t *controller);
+
+ /**
+ * @brief Process a request in this session.
+ *
+ * @param request request to process
+ * @param response response to send
+ */
+ void (*process)(session_t *this, request_t *request, response_t *response);
+
+ /**
+ * @brief Destroy the session_t.
+ *
+ * @param this calling object
+ */
+ void (*destroy) (session_t *this);
+};
+
+/**
+ * @brief Create a session.
+ *
+ * @param context user defined session context instance
+ */
+session_t *session_create(context_t *context);
+
+#endif /* SESSION_H_ */
diff --git a/src/manager/lib/template.c b/src/manager/lib/template.c
new file mode 100644
index 000000000..f168f9a56
--- /dev/null
+++ b/src/manager/lib/template.c
@@ -0,0 +1,138 @@
+/**
+ * @file template.c
+ *
+ * @brief Implementation of template_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "template.h"
+
+#include <ClearSilver/ClearSilver.h>
+
+#include <library.h>
+
+typedef struct private_template_t private_template_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_template_t {
+
+ /**
+ * public functions
+ */
+ template_t public;
+
+ /**
+ * template file
+ */
+ char *file;
+
+ /**
+ * clearsilver HDF dataset
+ */
+ HDF *hdf;
+};
+
+/**
+ * clearsilver cs_render callback function
+ */
+static NEOERR* render_cb(response_t *response, char *str)
+{
+ response->print(response, str);
+ return NULL;
+}
+
+/**
+ * Implementation of template_t.render.
+ */
+static void render(private_template_t *this, response_t *response)
+{
+ NEOERR* err;
+ CSPARSE *parse;
+
+ hdf_remove_tree(this->hdf, "");
+
+ err = cs_init(&parse, this->hdf);
+ if (!err)
+ {
+ err = cs_parse_file(parse, this->file);
+ if (!err)
+ {
+ err = cs_render(parse, response, (CSOUTFUNC)render_cb);
+ if (!err)
+ {
+ cs_destroy(&parse);
+ return;
+ }
+ }
+ cs_destroy(&parse);
+ }
+ nerr_log_error(err);
+ return;
+}
+
+/**
+ * Implementation of template_t.set.
+ */
+static void set(private_template_t *this, char *key, char *value)
+{
+ hdf_set_value(this->hdf, key, value);
+}
+
+/**
+ * Implementation of template_t.setf.
+ */
+static void setf(private_template_t *this, char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ hdf_set_valuevf(this->hdf, format, args);
+ va_end(args);
+}
+
+/**
+ * Implementation of template_t.destroy
+ */
+static void destroy(private_template_t *this)
+{
+ hdf_destroy(&this->hdf);
+ free(this->file);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+template_t *template_create(char *file)
+{
+ private_template_t *this = malloc_thing(private_template_t);
+
+ this->public.render = (void(*)(template_t*,response_t*))render;
+ this->public.set = (void(*)(template_t*, char *, char*))set;
+ this->public.setf = (void(*)(template_t*, char *format, ...))setf;
+ this->public.destroy = (void(*)(template_t*))destroy;
+
+ this->file = strdup(file);
+ this->hdf = NULL;
+
+ hdf_init(&this->hdf);
+ return &this->public;
+}
+
diff --git a/src/manager/lib/template.h b/src/manager/lib/template.h
new file mode 100644
index 000000000..1a8c2f7b7
--- /dev/null
+++ b/src/manager/lib/template.h
@@ -0,0 +1,76 @@
+/**
+ * @file template.h
+ *
+ * @brief Interface of template_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef TEMPLATE_H_
+#define TEMPLATE_H_
+
+#include "response.h"
+
+typedef struct template_t template_t;
+
+/**
+ * @brief Template engine based on ClearSilver.
+ *
+ */
+struct template_t {
+
+ /**
+ * @brief Set a template value.
+ *
+ * @param key key to set
+ * @param value value to set key to
+ */
+ void (*set)(template_t *this, char *key, char *value);
+
+ /**
+ * @brief Set a template value using format strings.
+ *
+ * Format string is in the form "key=value", where printf like format
+ * substitution occurs over the whole string.
+ *
+ * @param format printf like format string
+ * @param ... variable argument list
+ */
+ void (*setf)(template_t *this, char *format, ...);
+
+ /**
+ * @brief Render a template to a response object.
+ *
+ * @param response response to render to
+ * @return rendered template string
+ */
+ void (*render)(template_t *this, response_t *response);
+
+ /**
+ * @brief Destroy the template_t.
+ */
+ void (*destroy) (template_t *this);
+};
+
+/**
+ * @brief Create a template from a file.
+ *
+ * @param file template file
+ */
+template_t *template_create(char *file);
+
+#endif /* TEMPLATE_H_ */
diff --git a/src/manager/main.c b/src/manager/main.c
new file mode 100644
index 000000000..5aec02156
--- /dev/null
+++ b/src/manager/main.c
@@ -0,0 +1,62 @@
+/**
+ * @file main.c
+ *
+ * @brief Implementation of dispatcher_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include <dispatcher.h>
+#include <stdio.h>
+
+#include "manager.h"
+#include "database.h"
+#include "controller/static_controller.h"
+#include "controller/auth_controller.h"
+#include "controller/status_controller.h"
+#include "controller/gateway_controller.h"
+
+#define DBFILE "/usr/local/libexec/ipsec/sqlite.db"
+
+int main (int arc, char *argv[])
+{
+ dispatcher_t *dispatcher;
+ database_t *database;
+
+ database = database_create(DBFILE);
+ if (database == NULL)
+ {
+ fprintf(stderr, "opening database '%s' failed.\n", DBFILE);
+ return 1;
+ }
+
+ dispatcher = dispatcher_create((context_constructor_t)manager_create, database);
+
+ dispatcher->add_controller(dispatcher, static_controller_create, NULL);
+ dispatcher->add_controller(dispatcher, auth_controller_create, NULL);
+ dispatcher->add_controller(dispatcher, status_controller_create, NULL);
+ dispatcher->add_controller(dispatcher, gateway_controller_create, NULL);
+
+ dispatcher->run(dispatcher, 10);
+
+ dispatcher->waitsignal(dispatcher);
+
+ dispatcher->destroy(dispatcher);
+ database->destroy(database);
+
+ return 0;
+}
diff --git a/src/manager/manager.c b/src/manager/manager.c
new file mode 100644
index 000000000..dc27f86a6
--- /dev/null
+++ b/src/manager/manager.c
@@ -0,0 +1,160 @@
+/**
+ * @file manager.c
+ *
+ * @brief Implementation of manager_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#include "manager.h"
+
+#include "gateway.h"
+
+#include <utils/linked_list.h>
+
+typedef struct private_manager_t private_manager_t;
+
+/**
+ * private data of manager
+ */
+struct private_manager_t {
+
+ /**
+ * public functions
+ */
+ manager_t public;
+
+ /**
+ * underlying database
+ */
+ database_t *db;
+
+ /**
+ * user id, if we are logged in
+ */
+ int user;
+
+ /**
+ * selected gateway
+ */
+ gateway_t *gateway;
+};
+
+/**
+ * Implementation of manager_t.create_gateway_enumerator.
+ */
+static enumerator_t* create_gateway_enumerator(private_manager_t *this)
+{
+ return this->db->create_gateway_enumerator(this->db, this->user);
+}
+
+/**
+ * Implementation of manager_t.select_gateway.
+ */
+static gateway_t* select_gateway(private_manager_t *this, int select_id)
+{
+ if (select_id != 0)
+ {
+ enumerator_t *enumerator;
+ int id, port;
+ char *name, *address;
+ host_t *host;
+
+ if (this->gateway) this->gateway->destroy(this->gateway);
+ this->gateway = NULL;
+
+ enumerator = this->db->create_gateway_enumerator(this->db, this->user);
+ while (enumerator->enumerate(enumerator, &id, &name, &port, &address))
+ {
+ if (select_id == id)
+ {
+ if (port != 0)
+ {
+ host = host_create_from_string(address, port);
+ if (host)
+ {
+ this->gateway = gateway_create(name, host);
+ }
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return this->gateway;
+}
+
+/**
+ * Implementation of manager_t.logged_in.
+ */
+static bool logged_in(private_manager_t *this)
+{
+ return this->user != 0;
+}
+
+/**
+ * Implementation of manager_t.login.
+ */
+static bool login(private_manager_t *this, char *username, char *password)
+{
+ if (!this->user)
+ {
+ this->user = this->db->login(this->db, username, password);
+ }
+ return this->user != 0;
+}
+
+/**
+ * Implementation of manager_t.logout.
+ */
+static void logout(private_manager_t *this)
+{
+ this->user = 0;
+ this->gateway->destroy(this->gateway);
+ this->gateway = NULL;
+}
+
+/**
+ * Implementation of manager_t.destroy
+ */
+static void destroy(private_manager_t *this)
+{
+ if (this->gateway) this->gateway->destroy(this->gateway);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+manager_t *manager_create(database_t *database)
+{
+ private_manager_t *this = malloc_thing(private_manager_t);
+
+ this->public.login = (bool(*)(manager_t*, char *username, char *password))login;
+ this->public.logged_in = (bool(*)(manager_t*))logged_in;
+ this->public.logout = (void(*)(manager_t*))logout;
+ this->public.create_gateway_enumerator = (enumerator_t*(*)(manager_t*))create_gateway_enumerator;
+ this->public.select_gateway = (gateway_t*(*)(manager_t*, int id))select_gateway;
+ this->public.context.destroy = (void(*)(context_t*))destroy;
+
+ this->user = 0;
+ this->db = database;
+ this->gateway = NULL;
+
+ return &this->public;
+}
+
diff --git a/src/manager/manager.h b/src/manager/manager.h
new file mode 100644
index 000000000..4235618cd
--- /dev/null
+++ b/src/manager/manager.h
@@ -0,0 +1,93 @@
+/**
+ * @file manager.h
+ *
+ * @brief Interface of manager_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * 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 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ */
+
+#ifndef MANAGER_H_
+#define MANAGER_H_
+
+#include "database.h"
+#include "gateway.h"
+
+#include <context.h>
+
+#include <utils/iterator.h>
+
+typedef struct manager_t manager_t;
+
+/**
+ * @brief The manager, manages multiple gateways.
+ */
+struct manager_t {
+
+ /**
+ * implements context_t interface
+ */
+ context_t context;
+
+ /**
+ * @brief Create an iterator over all configured gateways.
+ *
+ * enumerate() arguments: int id, char *name, int port, char *address
+ * If port is 0, address is a Unix socket address.
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_gateway_enumerator)(manager_t *this);
+
+ /**
+ * @brief Select a gateway.
+ *
+ * If id is 0, the previously selected gateway is returned. If none has
+ * been selected yet, NULL is returned.
+ *
+ * @param id id of the gateway (from enumerate), or 0
+ * @return selected gateway, or NULL
+ */
+ gateway_t* (*select_gateway)(manager_t *this, int id);
+
+ /**
+ * @brief Try to log in.
+ *
+ * @param username username
+ * @param password cleartext password
+ * @return TRUE if login successful
+ */
+ bool (*login)(manager_t *this, char *username, char *password);
+
+ /**
+ * @brief Check if user logged in.
+ *
+ * @return TRUE if logged in
+ */
+ bool (*logged_in)(manager_t *this);
+
+ /**
+ * @brief Log out.
+ */
+ void (*logout)(manager_t *this);
+};
+
+/**
+ * @brief Create a manager instance.
+ */
+manager_t *manager_create(database_t *database);
+
+#endif /* MANAGER_H_ */
diff --git a/src/manager/templates/auth/login.cs b/src/manager/templates/auth/login.cs
new file mode 100644
index 000000000..f84c6307c
--- /dev/null
+++ b/src/manager/templates/auth/login.cs
@@ -0,0 +1,15 @@
+<?cs include:"templates/header.cs" ?>
+<form method="post" action="<?cs var:action ?>">
+ <table width="100%">
+ <tr>
+ <td>Username</td><td><input type="text" name="username" value="" size="25" /></td>
+ </tr>
+ <tr>
+ <td>Password</td><td><input type="password" name="password" value="" size="25" /></td>
+ </tr>
+ <tr>
+ <td/><td><input type="submit" value="Login"/></td>
+ </tr>
+</table>
+</form>
+<?cs include:"templates/footer.cs" ?>
diff --git a/src/manager/templates/auth/logout.cs b/src/manager/templates/auth/logout.cs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/manager/templates/auth/logout.cs
diff --git a/src/manager/templates/footer.cs b/src/manager/templates/footer.cs
new file mode 100644
index 000000000..b605728ee
--- /dev/null
+++ b/src/manager/templates/footer.cs
@@ -0,0 +1,2 @@
+ </body>
+</html>
diff --git a/src/manager/templates/gateway/list.cs b/src/manager/templates/gateway/list.cs
new file mode 100644
index 000000000..5cc8603b1
--- /dev/null
+++ b/src/manager/templates/gateway/list.cs
@@ -0,0 +1,13 @@
+<?cs include:"templates/header.cs" ?>
+<form method="post" action="<?cs var:action ?>">
+ <p>
+ <select name="gateway" size="1">
+ <?cs each:gateway = gateways ?>
+ <option value="<?cs name:gateway ?>"><?cs var:gateway.name ?> (<?cs var:gateway.address ?>)</option>
+ <?cs /each ?>
+ </select>
+ </p>
+ <input type="submit" value="Select"/>
+ <p>
+</form>
+<?cs include:"templates/footer.cs" ?>
diff --git a/src/manager/templates/header.cs b/src/manager/templates/header.cs
new file mode 100644
index 000000000..b417ef916
--- /dev/null
+++ b/src/manager/templates/header.cs
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <link rel="stylesheet" type="text/css" href="static/stlye.css" />
+ <title>strongSwan management</title>
+ </head>
+ <body>
diff --git a/src/manager/templates/static/style.css b/src/manager/templates/static/style.css
new file mode 100644
index 000000000..986ae066e
--- /dev/null
+++ b/src/manager/templates/static/style.css
@@ -0,0 +1,188 @@
+html {
+ height:100%;
+ width: auto;
+ margin:0;
+ padding:0;
+}
+
+
+body {
+ font-family: Verdana, Helvetica, sans-serif;
+ font-size: 12px;
+ width: 100%;
+ height:100%;
+ margin:0;
+ padding:0;
+ background-color: #EEEEEE;
+}
+
+h1 {
+ color: #203781;
+ font-size: 18px;
+ font-weight: bold;
+}
+
+h2 {
+ color: #203781;
+ font-size: 17px;
+ font-weight: bold;
+}
+
+h3 {
+ color: #203781;
+ font-size: 16px;
+ font-weight: bold;
+}
+
+h4 {
+ color: #203781;
+ font-size: 15px;
+ font-weight: bold;
+}
+
+p {
+ line-height: 1.2;
+ font-size: 11px;
+}
+
+a {
+ color: black;
+ font-size: 12px;
+}
+
+#headermain {
+ min-height: 100%;
+ background-color: white;
+ margin-left: 188px;
+}
+
+/* ##### Header ##### */
+
+#header {
+ width: 100%;
+ height: 30px;
+ background-color: #EEEEEE;
+}
+
+.gatewayname{
+ padding-top: 5px;
+ padding-left: 30px;
+ font-size: 12px;
+}
+
+/* ##### Left Side Bar ##### */
+
+.leftSideBar {
+ padding-top: 30px;
+ padding-left: 8px;
+ padding-right: 8px;
+ width: 170px;
+ float: left;
+}
+
+.leftSideBar .sideBarTitle {
+ color: black;
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0.1ex 0 0.1ex 0;
+}
+
+.leftSideBar a {
+ color: #203781;
+ text-decoration: none;
+ display: block;
+ margin: 0;
+ padding: 0.8ex 1ex;
+}
+
+.leftSideBar a:hover {
+ color: black;
+ background-color: lightgrey;
+ text-decoration: none;
+}
+
+/* ##### Main ##### */
+
+#main {
+ padding-top: 10px;
+ padding-left: 30px;
+ color: black;
+ text-align: justify;
+ line-height: 1.5em;
+}
+
+/* ##### From Selection ##### */
+
+.formbody {
+ background-color: white;
+ height: auto;
+}
+
+.formbox {
+ width: 492px;
+ margin-top: 100px;
+ margin-left: auto;
+ margin-right: auto;
+ border-color: #333;
+ border-width: 1px;
+ border-style: solid;
+ padding: 10px;
+}
+
+.formselection {
+ background-color: #EEEEEE;
+ border-color: #333;
+ border-width: 1px;
+ border-style: solid;
+}
+
+.selection {
+ background-color: white;
+ border-color: #333;
+ border-style: solid;
+ margin-left: 12px;
+ margin-right: 4px;
+ border-width: 1px;
+ width: 400px;
+}
+
+.button {
+ font-size: 12px;
+ font-weight: bold;
+ width: 50px;
+ border-color: #333;
+ border-width: 1px;
+ border-style: solid;
+ background-color: lightgrey;
+}
+
+.message {
+ color: red;
+}
+
+/* ##### Tables ##### */
+
+th {
+ padding-right: 15px;
+}
+
+td {
+ padding-right: 15px;
+}
+
+/* ##### Lists ##### */
+
+ul {
+ list-style: None;
+ padding-left: 0;
+}
+
+li {
+ padding-bottom: 5px;
+}
+
+/* ##### Labels ##### */
+
+label {
+ font-weight: bold;
+} \ No newline at end of file
diff --git a/src/manager/templates/status/ikesalist.cs b/src/manager/templates/status/ikesalist.cs
new file mode 100644
index 000000000..f9becf8d0
--- /dev/null
+++ b/src/manager/templates/status/ikesalist.cs
@@ -0,0 +1 @@
+<?cs var:xml ?>