first revision of new manager webapp
authorMartin Willi <martin@strongswan.org>
Tue, 11 Sep 2007 15:22:02 +0000 (15:22 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 11 Sep 2007 15:22:02 +0000 (15:22 -0000)
36 files changed:
src/manager/Makefile.am [new file with mode: 0644]
src/manager/controller/auth_controller.c [new file with mode: 0644]
src/manager/controller/auth_controller.h [new file with mode: 0644]
src/manager/controller/gateway_controller.c [new file with mode: 0644]
src/manager/controller/gateway_controller.h [new file with mode: 0644]
src/manager/controller/static_controller.c [new file with mode: 0644]
src/manager/controller/static_controller.h [new file with mode: 0644]
src/manager/controller/status_controller.c [new file with mode: 0644]
src/manager/controller/status_controller.h [new file with mode: 0644]
src/manager/database.c [new file with mode: 0644]
src/manager/database.h [new file with mode: 0644]
src/manager/gateway.c [new file with mode: 0644]
src/manager/gateway.h [new file with mode: 0644]
src/manager/lib/context.h [new file with mode: 0644]
src/manager/lib/controller.h [new file with mode: 0644]
src/manager/lib/dispatcher.c [new file with mode: 0644]
src/manager/lib/dispatcher.h [new file with mode: 0644]
src/manager/lib/enumerator.h [new file with mode: 0644]
src/manager/lib/request.c [new file with mode: 0644]
src/manager/lib/request.h [new file with mode: 0644]
src/manager/lib/response.c [new file with mode: 0644]
src/manager/lib/response.h [new file with mode: 0644]
src/manager/lib/session.c [new file with mode: 0644]
src/manager/lib/session.h [new file with mode: 0644]
src/manager/lib/template.c [new file with mode: 0644]
src/manager/lib/template.h [new file with mode: 0644]
src/manager/main.c [new file with mode: 0644]
src/manager/manager.c [new file with mode: 0644]
src/manager/manager.h [new file with mode: 0644]
src/manager/templates/auth/login.cs [new file with mode: 0644]
src/manager/templates/auth/logout.cs [new file with mode: 0644]
src/manager/templates/footer.cs [new file with mode: 0644]
src/manager/templates/gateway/list.cs [new file with mode: 0644]
src/manager/templates/header.cs [new file with mode: 0644]
src/manager/templates/static/style.css [new file with mode: 0644]
src/manager/templates/status/ikesalist.cs [new file with mode: 0644]

diff --git a/src/manager/Makefile.am b/src/manager/Makefile.am
new file mode 100644 (file)
index 0000000..d86110e
--- /dev/null
@@ -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 (file)
index 0000000..1026b5e
--- /dev/null
@@ -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 (file)
index 0000000..c90546a
--- /dev/null
@@ -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 (file)
index 0000000..3257621
--- /dev/null
@@ -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 (file)
index 0000000..5872e20
--- /dev/null
@@ -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 (file)
index 0000000..8968c87
--- /dev/null
@@ -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 (file)
index 0000000..8181a7a
--- /dev/null
@@ -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 (file)
index 0000000..eac4b67
--- /dev/null
@@ -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 (file)
index 0000000..a736dda
--- /dev/null
@@ -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 (file)
index 0000000..5e8eb78
--- /dev/null
@@ -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 (file)
index 0000000..7edcde4
--- /dev/null
@@ -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 (file)
index 0000000..b918da2
--- /dev/null
@@ -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 (file)
index 0000000..7b5d910
--- /dev/null
@@ -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 (file)
index 0000000..23c979b
--- /dev/null
@@ -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 (file)
index 0000000..92968d8
--- /dev/null
@@ -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 (file)
index 0000000..018122e
--- /dev/null
@@ -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 (file)
index 0000000..5119a1e
--- /dev/null
@@ -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 (file)
index 0000000..de272f9
--- /dev/null
@@ -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 (file)
index 0000000..2e12d36
--- /dev/null
@@ -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 (file)
index 0000000..852238a
--- /dev/null
@@ -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 (file)
index 0000000..ae74ab6
--- /dev/null
@@ -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 (file)
index 0000000..e3be2cf
--- /dev/null
@@ -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 (file)
index 0000000..be25f27
--- /dev/null
@@ -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 (file)
index 0000000..baaacd0
--- /dev/null
@@ -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 (file)
index 0000000..f168f9a
--- /dev/null
@@ -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 (file)
index 0000000..1a8c2f7
--- /dev/null
@@ -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 (file)
index 0000000..5aec021
--- /dev/null
@@ -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 (file)
index 0000000..dc27f86
--- /dev/null
@@ -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 (file)
index 0000000..4235618
--- /dev/null
@@ -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 (file)
index 0000000..f84c630
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/src/manager/templates/footer.cs b/src/manager/templates/footer.cs
new file mode 100644 (file)
index 0000000..b605728
--- /dev/null
@@ -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 (file)
index 0000000..5cc8603
--- /dev/null
@@ -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 (file)
index 0000000..b417ef9
--- /dev/null
@@ -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 (file)
index 0000000..986ae06
--- /dev/null
@@ -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 (file)
index 0000000..f9becf8
--- /dev/null
@@ -0,0 +1 @@
+<?cs var:xml ?>