From 965e99b5bff26d1f43273214a5f44e31611018e7 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 11 Sep 2007 15:22:02 +0000 Subject: [PATCH] first revision of new manager webapp --- src/manager/Makefile.am | 33 ++ src/manager/controller/auth_controller.c | 125 +++++++ src/manager/controller/auth_controller.h | 47 +++ src/manager/controller/gateway_controller.c | 147 +++++++++ src/manager/controller/gateway_controller.h | 47 +++ src/manager/controller/static_controller.c | 103 ++++++ src/manager/controller/static_controller.h | 47 +++ src/manager/controller/status_controller.c | 136 ++++++++ src/manager/controller/status_controller.h | 47 +++ src/manager/database.c | 195 +++++++++++ src/manager/database.h | 69 ++++ src/manager/gateway.c | 153 +++++++++ src/manager/gateway.h | 58 ++++ src/manager/lib/context.h | 47 +++ src/manager/lib/controller.h | 75 +++++ src/manager/lib/dispatcher.c | 348 ++++++++++++++++++++ src/manager/lib/dispatcher.h | 78 +++++ src/manager/lib/enumerator.h | 49 +++ src/manager/lib/request.c | 306 +++++++++++++++++ src/manager/lib/request.h | 73 ++++ src/manager/lib/response.c | 223 +++++++++++++ src/manager/lib/response.h | 95 ++++++ src/manager/lib/session.c | 185 +++++++++++ src/manager/lib/session.h | 75 +++++ src/manager/lib/template.c | 138 ++++++++ src/manager/lib/template.h | 76 +++++ src/manager/main.c | 62 ++++ src/manager/manager.c | 160 +++++++++ src/manager/manager.h | 93 ++++++ src/manager/templates/auth/login.cs | 15 + src/manager/templates/auth/logout.cs | 0 src/manager/templates/footer.cs | 2 + src/manager/templates/gateway/list.cs | 13 + src/manager/templates/header.cs | 8 + src/manager/templates/static/style.css | 188 +++++++++++ src/manager/templates/status/ikesalist.cs | 1 + 36 files changed, 3517 insertions(+) create mode 100644 src/manager/Makefile.am create mode 100644 src/manager/controller/auth_controller.c create mode 100644 src/manager/controller/auth_controller.h create mode 100644 src/manager/controller/gateway_controller.c create mode 100644 src/manager/controller/gateway_controller.h create mode 100644 src/manager/controller/static_controller.c create mode 100644 src/manager/controller/static_controller.h create mode 100644 src/manager/controller/status_controller.c create mode 100644 src/manager/controller/status_controller.h create mode 100644 src/manager/database.c create mode 100644 src/manager/database.h create mode 100644 src/manager/gateway.c create mode 100644 src/manager/gateway.h create mode 100644 src/manager/lib/context.h create mode 100644 src/manager/lib/controller.h create mode 100644 src/manager/lib/dispatcher.c create mode 100644 src/manager/lib/dispatcher.h create mode 100644 src/manager/lib/enumerator.h create mode 100644 src/manager/lib/request.c create mode 100644 src/manager/lib/request.h create mode 100644 src/manager/lib/response.c create mode 100644 src/manager/lib/response.h create mode 100644 src/manager/lib/session.c create mode 100644 src/manager/lib/session.h create mode 100644 src/manager/lib/template.c create mode 100644 src/manager/lib/template.h create mode 100644 src/manager/main.c create mode 100644 src/manager/manager.c create mode 100644 src/manager/manager.h create mode 100644 src/manager/templates/auth/login.cs create mode 100644 src/manager/templates/auth/logout.cs create mode 100644 src/manager/templates/footer.cs create mode 100644 src/manager/templates/gateway/list.cs create mode 100644 src/manager/templates/header.cs create mode 100644 src/manager/templates/static/style.css create mode 100644 src/manager/templates/status/ikesalist.cs diff --git a/src/manager/Makefile.am b/src/manager/Makefile.am new file mode 100644 index 000000000..d86110e46 --- /dev/null +++ b/src/manager/Makefile.am @@ -0,0 +1,33 @@ +ipsec_PROGRAMS = manager + +manager_SOURCES = \ +main.c manager.c manager.h gateway.h gateway.c database.h database.c \ +controller/auth_controller.c controller/auth_controller.h \ +controller/static_controller.c controller/static_controller.h \ +controller/status_controller.c controller/status_controller.h \ +controller/gateway_controller.c controller/gateway_controller.h + +manager_LDADD = $(top_builddir)/src/manager/libappserv.la -lsqlite3 + + + +lib_LTLIBRARIES = libappserv.la + +libappserv_la_SOURCES = \ +lib/context.h lib/dispatcher.c lib/request.h lib/response.h lib/session.h \ +lib/controller.h lib/dispatcher.h lib/request.c lib/response.c lib/session.c \ +lib/template.h lib/template.c + +libappserv_la_LDFLAGS = -lstrongswan -lfcgi -lpthread -lneo_cs -lneo_utl + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/manager/lib -I/usr/include/ClearSilver + + +ipsec_templatesdir = ${ipsecdir}/templates +ipsec_templates_DATA = templates/header.cs templates/footer.cs + +ipsec_templates_authdir = ${ipsec_templatesdir}/auth +ipsec_templates_auth_DATA = templates/auth/login.cs templates/auth/logout.cs + +ipsec_templates_staticdir = ${ipsec_templatesdir}/static +ipsec_templates_static_DATA = templates/static/style.css diff --git a/src/manager/controller/auth_controller.c b/src/manager/controller/auth_controller.c new file mode 100644 index 000000000..1026b5eeb --- /dev/null +++ b/src/manager/controller/auth_controller.c @@ -0,0 +1,125 @@ +/** + * @file auth_controller.c + * + * @brief Implementation of auth_controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +#include + + +typedef struct private_auth_controller_t private_auth_controller_t; + +/** + * private data of the task manager + */ +struct private_auth_controller_t { + + /** + * public functions + */ + auth_controller_t public; + + /** + * manager instance + */ + manager_t *manager; +}; + +static void login(private_auth_controller_t *this, + request_t *request, response_t *response) +{ + template_t *t = template_create("templates/auth/login.cs"); + t->set(t, "action", "check"); + t->render(t, response); + t->destroy(t); +} + +static void check(private_auth_controller_t *this, + request_t *request, response_t *response) +{ + char *username, *password; + + username = request->get_post_data(request, "username"); + password = request->get_post_data(request, "password"); + if (username && password && + this->manager->login(this->manager, username, password)) + { + response->redirect(response, "status/test"); + } + else + { + response->redirect(response, "auth/login"); + } +} + +static void logout(private_auth_controller_t *this, + request_t *request, response_t *response) +{ + this->manager->logout(this->manager); + response->redirect(response, "auth/login"); +} + +/** + * Implementation of controller_t.get_name + */ +static char* get_name(private_auth_controller_t *this) +{ + return "auth"; +} + +/** + * Implementation of controller_t.get_handler + */ +static controller_handler_t get_handler(private_auth_controller_t *this, char *name) +{ + if (streq(name, "login")) return (controller_handler_t)login; + if (streq(name, "check")) return (controller_handler_t)check; + if (streq(name, "logout")) return (controller_handler_t)logout; + return NULL; +} + +/** + * Implementation of controller_t.destroy + */ +static void destroy(private_auth_controller_t *this) +{ + free(this); +} + +/* + * see header file + */ +controller_t *auth_controller_create(context_t *context, void *param) +{ + private_auth_controller_t *this = malloc_thing(private_auth_controller_t); + + this->public.controller.get_name = (char*(*)(controller_t*))get_name; + this->public.controller.get_handler = (controller_handler_t(*)(controller_t*,char*))get_handler; + this->public.controller.destroy = (void(*)(controller_t*))destroy; + + this->manager = (manager_t*)context; + + return &this->public.controller; +} + diff --git a/src/manager/controller/auth_controller.h b/src/manager/controller/auth_controller.h new file mode 100644 index 000000000..c90546a17 --- /dev/null +++ b/src/manager/controller/auth_controller.h @@ -0,0 +1,47 @@ +/** + * @file auth_controller.h + * + * @brief Interface of auth_controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct auth_controller_t auth_controller_t; + +/** + * @brief Authentication controller. + */ +struct auth_controller_t { + + /** + * Implements controller_t interface. + */ + controller_t controller; +}; + +/** + * @brief Create a auth_controller controller instance. + */ +controller_t *auth_controller_create(context_t *context, void *param); + +#endif /* AUTH_CONTROLLER_H_ */ diff --git a/src/manager/controller/gateway_controller.c b/src/manager/controller/gateway_controller.c new file mode 100644 index 000000000..32576216e --- /dev/null +++ b/src/manager/controller/gateway_controller.c @@ -0,0 +1,147 @@ +/** + * @file gateway_controller.c + * + * @brief Implementation of gateway_controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +#include + + +typedef struct private_gateway_controller_t private_gateway_controller_t; + +/** + * private data of the gateway_controller + */ +struct private_gateway_controller_t { + + /** + * public functions + */ + gateway_controller_t public; + + /** + * manager instance + */ + manager_t *manager; + +}; + +static void list(private_gateway_controller_t *this, + request_t *request, response_t *response) +{ + template_t *t; + enumerator_t *enumerator; + char *name, *address; + int id, port; + + t = template_create("templates/gateway/list.cs"); + enumerator = this->manager->create_gateway_enumerator(this->manager); + while (enumerator->enumerate(enumerator, &id, &name, &port, &address)) + { + t->setf(t, "gateways.%d.name=%s", id, name); + if (port) + { + t->setf(t, "gateways.%d.address=tcp://%s:%d", id, address, port); + } + else + { + t->setf(t, "gateways.%d.address=unix://%s", id, address); + } + } + enumerator->destroy(enumerator); + t->set(t, "action", "select"); + t->render(t, response); + t->destroy(t); +} + +static void _select(private_gateway_controller_t *this, + request_t *request, response_t *response) +{ + char *id; + + id = request->get_post_data(request, "gateway"); + if (id) + { + if (this->manager->select_gateway(this->manager, atoi(id))) + { + response->redirect(response, "status/ikesalist"); + return; + } + } + response->printf(response, "selecting dings failed: %s", id); +} + +/** + * redirect to authentication login + */ +static void login(private_gateway_controller_t *this, + request_t *request, response_t *response) +{ + response->redirect(response, "auth/login"); +} + +/** + * Implementation of controller_t.get_name + */ +static char* get_name(private_gateway_controller_t *this) +{ + return "gateway"; +} + +/** + * Implementation of controller_t.get_handler + */ +static controller_handler_t get_handler(private_gateway_controller_t *this, char *name) +{ + if (!this->manager->logged_in(this->manager)) return (controller_handler_t)login; + if (streq(name, "list")) return (controller_handler_t)list; + if (streq(name, "select")) return (controller_handler_t)_select; + return NULL; +} + +/** + * Implementation of controller_t.destroy + */ +static void destroy(private_gateway_controller_t *this) +{ + free(this); +} + +/* + * see header file + */ +controller_t *gateway_controller_create(context_t *context, void *param) +{ + private_gateway_controller_t *this = malloc_thing(private_gateway_controller_t); + + this->public.controller.get_name = (char*(*)(controller_t*))get_name; + this->public.controller.get_handler = (controller_handler_t(*)(controller_t*,char*))get_handler; + this->public.controller.destroy = (void(*)(controller_t*))destroy; + + this->manager = (manager_t*)context; + + return &this->public.controller; +} + diff --git a/src/manager/controller/gateway_controller.h b/src/manager/controller/gateway_controller.h new file mode 100644 index 000000000..5872e20e2 --- /dev/null +++ b/src/manager/controller/gateway_controller.h @@ -0,0 +1,47 @@ +/** + * @file gateway_controller.h + * + * @brief Interface of gateway_controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct gateway_controller_t gateway_controller_t; + +/** + * @brief Status controller. + */ +struct gateway_controller_t { + + /** + * Implements controller_t interface. + */ + controller_t controller; +}; + +/** + * @brief Create a gateway_controller controller instance. + */ +controller_t *gateway_controller_create(context_t *context, void *param); + +#endif /* GATEWAY_CONTROLLER_H_ */ diff --git a/src/manager/controller/static_controller.c b/src/manager/controller/static_controller.c new file mode 100644 index 000000000..8968c873c --- /dev/null +++ b/src/manager/controller/static_controller.c @@ -0,0 +1,103 @@ +/** + * @file static_controller.c + * + * @brief Implementation of static_controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +#include + + +typedef struct private_static_controller_t private_static_controller_t; + +/** + * private data of the task manager + */ +struct private_static_controller_t { + + /** + * public functions + */ + static_controller_t public; + + /** + * manager instance + */ + manager_t *manager; + +}; + +/** + * serve style.css + */ +static void style(private_static_controller_t *this, + request_t *request, response_t *response) +{ + template_t *t = template_create("templates/static/style.css"); + response->set_content_type(response, "text/css"); + t->render(t, response); + t->destroy(t); +} + +/** + * Implementation of controller_t.get_name + */ +static char* get_name(private_static_controller_t *this) +{ + return "static"; +} + +/** + * Implementation of controller_t.get_handler + */ +static controller_handler_t get_handler(private_static_controller_t *this, char *name) +{ + if (streq(name, "style.css")) return (controller_handler_t)style; + return NULL; +} + +/** + * Implementation of controller_t.destroy + */ +static void destroy(private_static_controller_t *this) +{ + free(this); +} + +/* + * see header file + */ +controller_t *static_controller_create(context_t *context, void *param) +{ + private_static_controller_t *this = malloc_thing(private_static_controller_t); + + this->public.controller.get_name = (char*(*)(controller_t*))get_name; + this->public.controller.get_handler = (controller_handler_t(*)(controller_t*,char*))get_handler; + this->public.controller.destroy = (void(*)(controller_t*))destroy; + + this->manager = (manager_t*)context; + + return &this->public.controller; +} + diff --git a/src/manager/controller/static_controller.h b/src/manager/controller/static_controller.h new file mode 100644 index 000000000..8181a7a16 --- /dev/null +++ b/src/manager/controller/static_controller.h @@ -0,0 +1,47 @@ +/** + * @file static_controller.h + * + * @brief Interface of static_controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct static_controller_t static_controller_t; + +/** + * @brief Static controller, serves static files. + */ +struct static_controller_t { + + /** + * Implements controller_t interface. + */ + controller_t controller; +}; + +/** + * @brief Create a static_controller controller instance. + */ +controller_t *static_controller_create(context_t *context, void *param); + +#endif /* STATIC_CONTROLLER_H_ */ diff --git a/src/manager/controller/status_controller.c b/src/manager/controller/status_controller.c new file mode 100644 index 000000000..eac4b67cf --- /dev/null +++ b/src/manager/controller/status_controller.c @@ -0,0 +1,136 @@ +/** + * @file status_controller.c + * + * @brief Implementation of status_controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +#include + + +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, "" + "" + "" + "" + ""); + + response->set_content_type(response, "text/xml"); + template_t *t = template_create("templates/status/ikesalist.cs"); + t->set(t, "xml", str); + t->render(t, response); + t->destroy(t); + + free(str); +} + +/** + * redirect to authentication login + */ +static void login(private_status_controller_t *this, + request_t *request, response_t *response) +{ + response->redirect(response, "auth/login"); +} + +/** + * redirect to gateway selection + */ +static void selection(private_status_controller_t *this, + request_t *request, response_t *response) +{ + response->redirect(response, "gateway/list"); +} + +/** + * Implementation of controller_t.get_name + */ +static char* get_name(private_status_controller_t *this) +{ + return "status"; +} + +/** + * Implementation of controller_t.get_handler + */ +static controller_handler_t get_handler(private_status_controller_t *this, char *name) +{ + if (!this->manager->logged_in(this->manager)) return (controller_handler_t)login; + if (this->manager->select_gateway(this->manager, 0) == NULL) return (controller_handler_t)selection; + if (streq(name, "ikesalist")) return (controller_handler_t)ikesalist; + return NULL; +} + +/** + * Implementation of controller_t.destroy + */ +static void destroy(private_status_controller_t *this) +{ + free(this); +} + +/* + * see header file + */ +controller_t *status_controller_create(context_t *context, void *param) +{ + private_status_controller_t *this = malloc_thing(private_status_controller_t); + + this->public.controller.get_name = (char*(*)(controller_t*))get_name; + this->public.controller.get_handler = (controller_handler_t(*)(controller_t*,char*))get_handler; + this->public.controller.destroy = (void(*)(controller_t*))destroy; + + this->count = 0; + this->manager = (manager_t*)context; + + return &this->public.controller; +} + diff --git a/src/manager/controller/status_controller.h b/src/manager/controller/status_controller.h new file mode 100644 index 000000000..a736dda83 --- /dev/null +++ b/src/manager/controller/status_controller.h @@ -0,0 +1,47 @@ +/** + * @file status_controller.h + * + * @brief Interface of status_controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct status_controller_t status_controller_t; + +/** + * @brief Status controller. + */ +struct status_controller_t { + + /** + * Implements controller_t interface. + */ + controller_t controller; +}; + +/** + * @brief Create a status_controller controller instance. + */ +controller_t *status_controller_create(context_t *context, void *param); + +#endif /* STATUS_CONTROLLER_H_ */ diff --git a/src/manager/database.c b/src/manager/database.c new file mode 100644 index 000000000..5e8eb78f7 --- /dev/null +++ b/src/manager/database.c @@ -0,0 +1,195 @@ +/** + * @file database.c + * + * @brief Implementation of database_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 +#include +#include + + +typedef struct private_database_t private_database_t; + +/** + * private data of database + */ +struct private_database_t { + + /** + * public functions + */ + database_t public; + + /** + * SQLite database handle + */ + sqlite3 *db; +}; + +/** + * database enumerator implements enumerator_t + */ +typedef struct { + enumerator_t enumerator; + sqlite3_stmt *stmt; +} db_enumerator_t; + +/** + * destroy a database enumerator + */ +static void db_enumerator_destroy(db_enumerator_t* this) +{ + sqlite3_finalize(this->stmt); + free(this); +} + +/** + * create a database enumerator + */ +static enumerator_t *db_enumerator_create(bool(*enumerate)(db_enumerator_t*,...), + sqlite3_stmt *stmt) +{ + db_enumerator_t *this = malloc_thing(db_enumerator_t); + this->enumerator.enumerate = (void*)enumerate; + this->enumerator.destroy = (void*)db_enumerator_destroy; + this->stmt = stmt; + return &this->enumerator; +} + +/** + * enumerator function for empty enumerator + */ +static bool empty_enumerate(enumerator_t *enumerator, ...) +{ + return FALSE; +} + +/** + * create an empty enumerator + */ +static enumerator_t* empty_enumerator_create() +{ + enumerator_t *this = malloc_thing(enumerator_t); + this->enumerate = empty_enumerate; + this->destroy = (void*)free; + return this; +} + +/** + * Implementation of database_t.login. + */ +static int login(private_database_t *this, char *username, char *password) +{ + sqlite3_stmt *stmt; + int uid = 0; + + if (sqlite3_prepare_v2(this->db, + "SELECT oid FROM users WHERE username = ? AND password = ?;", + -1, &stmt, NULL) == SQLITE_OK) + { + if (sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC) == SQLITE_OK && + sqlite3_bind_text(stmt, 2, password, -1, SQLITE_STATIC) == SQLITE_OK && + sqlite3_step(stmt) == SQLITE_ROW) + { + uid = sqlite3_column_int(stmt, 0); + } + sqlite3_finalize(stmt); + } + return uid; +} + +/** + * enumerate function for gateway enumrator + */ +static bool gateway_enumerate(db_enumerator_t* e, ...) +{ + va_list args; + int *id, *port; + const char **name, **address; + + va_start(args, e); + id = va_arg(args, typeof(id)); + name = va_arg(args, typeof(name)); + port = va_arg(args, typeof(port)); + address = va_arg(args, typeof(address)); + va_end(args); + + if (sqlite3_step(e->stmt) == SQLITE_ROW) + { + *id = sqlite3_column_int(e->stmt, 0); + *name = sqlite3_column_text(e->stmt, 1); + *port = sqlite3_column_int(e->stmt, 2); + *address = sqlite3_column_text(e->stmt, 3); + return TRUE; + } + return FALSE; +} + +/** + * Implementation of database_t.create_gateway_enumerator. + */ +static enumerator_t* create_gateway_enumerator(private_database_t *this, int user) +{ + sqlite3_stmt *stmt; + + if (sqlite3_prepare_v2(this->db, + "SELECT gateways.oid AS gid, name, port, address FROM " + "gateways, user_gateway AS ug ON gid = ug.gateway WHERE ug.user = ?;", + -1, &stmt, NULL) == SQLITE_OK) + { + if (sqlite3_bind_int(stmt, 1, user) == SQLITE_OK) + { + return db_enumerator_create((void*)gateway_enumerate, stmt); + } + sqlite3_finalize(stmt); + } + return empty_enumerator_create(); +} + +/** + * Implementation of database_t.destroy + */ +static void destroy(private_database_t *this) +{ + sqlite3_close(this->db); + free(this); +} + +/* + * see header file + */ +database_t *database_create(char *dbfile) +{ + private_database_t *this = malloc_thing(private_database_t); + + this->public.login = (int(*)(database_t*, char *username, char *password))login; + this->public.create_gateway_enumerator = (enumerator_t*(*)(database_t*,int))create_gateway_enumerator; + this->public.destroy = (void(*)(database_t*))destroy; + + if (sqlite3_open(dbfile, &this->db) != SQLITE_OK) + { + destroy(this); + return NULL; + } + return &this->public; +} + diff --git a/src/manager/database.h b/src/manager/database.h new file mode 100644 index 000000000..7edcde4fa --- /dev/null +++ b/src/manager/database.h @@ -0,0 +1,69 @@ +/** + * @file database.h + * + * @brief Interface of database_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + + +typedef struct database_t database_t; + +/** + * @brief Persistent database. + */ +struct database_t { + + /** + * @brief Try to log in using specified credentials. + * + * @param username username + * @param password plaintext password + * @return user ID if login good, 0 otherwise + */ + int (*login)(database_t *this, char *username, char *password); + + /** + * @brief Create an iterator over the gateways. + * + * enumerate() arguments: int id, char *name, int port, char *address + * If port is 0, address is a Unix socket address. + * + * @param user user Id + * @return enumerator + */ + enumerator_t* (*create_gateway_enumerator)(database_t *this, int user); + + /** + * @brief Destroy a database instance. + */ + void (*destroy)(database_t *this); +}; + +/** + * @brief Create a database instance. + * + * @param dbfile SQLite database file + */ +database_t *database_create(char *dbfile); + +#endif /* DATABASE_H_ */ diff --git a/src/manager/gateway.c b/src/manager/gateway.c new file mode 100644 index 000000000..b918da26d --- /dev/null +++ b/src/manager/gateway.c @@ -0,0 +1,153 @@ +/** + * @file gateway.c + * + * @brief Implementation of gateway_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 +#include +#include +#include + +typedef struct private_gateway_t private_gateway_t; + +/** + * private data of gateway + */ +struct private_gateway_t { + + /** + * public functions + */ + gateway_t public; + + /** + * name of the gateway + */ + char *name; + + /** + * connection information + */ + host_t *host; + + /** + * socket file descriptor, > 0 if connected + */ + int fd; +}; + +/** + * establish connection to gateway + */ +static bool connect_(private_gateway_t *this) +{ + if (this->fd >= 0) + { + close(this->fd); + } + this->fd = socket(AF_INET, SOCK_STREAM, 0); + if (this->fd < 0) + { + return FALSE; + } + if (connect(this->fd, this->host->get_sockaddr(this->host), + *this->host->get_sockaddr_len(this->host)) != 0) + { + close(this->fd); + this->fd = -1; + return FALSE; + } + return TRUE; +} + + +/** + * Implementation of gateway_t.request. + */ +static char* request(private_gateway_t *this, char *xml) +{ + if (this->fd < 0) + { + if (!connect_(this)) + { + return NULL; + } + } + while (TRUE) + { + char buf[8096]; + ssize_t len; + + len = strlen(xml); + if (send(this->fd, xml, len, 0) != len) + { + return NULL; + } + len = recv(this->fd, buf, sizeof(buf) - 1, 0); + if (len < 0) + { + return NULL; + } + if (len == 0) + { + if (!connect_(this)) + { + return NULL; + } + continue; + } + buf[len] = 0; + return strdup(buf); + } +} + +/** + * Implementation of gateway_t.destroy + */ +static void destroy(private_gateway_t *this) +{ + if (this->fd >= 0) + { + close(this->fd); + } + this->host->destroy(this->host); + free(this->name); + free(this); +} + +/* + * see header file + */ +gateway_t *gateway_create(char *name, host_t *host) +{ + private_gateway_t *this = malloc_thing(private_gateway_t); + + this->public.request = (char*(*)(gateway_t*, char *xml))request; + this->public.destroy = (void(*)(gateway_t*))destroy; + + this->name = strdup(name); + this->host = host; + this->fd = -1; + + return &this->public; +} + diff --git a/src/manager/gateway.h b/src/manager/gateway.h new file mode 100644 index 000000000..7b5d91045 --- /dev/null +++ b/src/manager/gateway.h @@ -0,0 +1,58 @@ +/** + * @file gateway.h + * + * @brief Interface of gateway_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct gateway_t gateway_t; + +/** + * @brief A connection to a gateway. + */ +struct gateway_t { + + /** + * @brief Send an XML request to the gateway. + * + * @param xml xml request string + * @return allocated xml response string + */ + char* (*request)(gateway_t *this, char *xml); + + /** + * @brief Destroy a gateway instance. + */ + void (*destroy)(gateway_t *this); +}; + +/** + * @brief Create a gateway instance. + * + * @param name name of the gateway + * @param host gateway connection endpoint + * @param + */ +gateway_t *gateway_create(char *name, host_t *host); + +#endif /* GATEWAY_H_ */ diff --git a/src/manager/lib/context.h b/src/manager/lib/context.h new file mode 100644 index 000000000..23c979b8e --- /dev/null +++ b/src/manager/lib/context.h @@ -0,0 +1,47 @@ +/** + * @file context.h + * + * @brief Interface of context_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CONTEXT_H_ +#define CONTEXT_H_ + +typedef struct context_t context_t; + +/** + * @brief Constructor function for a context + */ +typedef context_t *(*context_constructor_t)(void *param); + +/** + * @brief Custom session context + * + */ +struct context_t { + + /** + * @brief Destroy the context_t. + * + * @param this calling object + */ + void (*destroy) (context_t *this); +}; + +#endif /* CONTEXT_H_ */ diff --git a/src/manager/lib/controller.h b/src/manager/lib/controller.h new file mode 100644 index 000000000..92968d8a6 --- /dev/null +++ b/src/manager/lib/controller.h @@ -0,0 +1,75 @@ +/** + * @file controller.h + * + * @brief Interface controller_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef CONTROLLER_H_ +#define CONTROLLER_H_ + +#include "request.h" +#include "response.h" +#include "context.h" + +typedef struct controller_t controller_t; + +/** + * @brief Controller action handle function + * + * @param request http request + * @param response http response + */ +typedef void *(*controller_handler_t)(controller_t *this, request_t *request, response_t *response); + +/** + * @brief Constructor function for a controller + * + * @param context session specific context + * @param param user supplied param + */ +typedef controller_t *(*controller_constructor_t)(context_t* context, void *param); + +/** + * @brief Controller interface, to be implemented by users controllers. + * + */ +struct controller_t { + + /** + * @brief Get the name of the controller. + * + * @return name of the controller + */ + char* (*get_name)(controller_t *this); + + /** + * @brief Get the controllers handler function for an action name. + * + * @param name name of the action + * @return controllers handler + */ + controller_handler_t (*get_handler)(controller_t *this, char *name); + + /** + * @brief Destroy the controller instance. + */ + void (*destroy) (controller_t *this); +}; + +#endif /* CONTROLLER_H_ */ diff --git a/src/manager/lib/dispatcher.c b/src/manager/lib/dispatcher.c new file mode 100644 index 000000000..018122e6f --- /dev/null +++ b/src/manager/lib/dispatcher.c @@ -0,0 +1,348 @@ +/** + * @file dispatcher.c + * + * @brief Implementation of dispatcher_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 +#include +#include + +#include + +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**)¤t)) + { + 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, "
    "); + char **env = fcgi_req.envp; + while (*env) + { + FCGX_FPrintF(fcgi_req.out, "
  • %s
  • ", *env); + env++; + } + FCGX_FPrintF(fcgi_req.out, "
"); + */ + } + } +} + +/** + * Implementation of dispatcher_t.run. + */ +static void run(private_dispatcher_t *this, int threads) +{ + this->thread_count = threads; + this->threads = malloc(sizeof(pthread_t) * threads); + while (threads) + { + if (pthread_create(&this->threads[threads - 1], + NULL, (void*)dispatch, this) == 0) + { + threads--; + } + } +} + +/** + * Implementation of dispatcher_t.waitsignal. + */ +static void waitsignal(private_dispatcher_t *this) +{ + sigset_t set; + int sig; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + sigaddset(&set, SIGHUP); + sigprocmask(SIG_BLOCK, &set, NULL); + sigwait(&set, &sig); +} + +/** + * Implementation of dispatcher_t.destroy + */ +static void destroy(private_dispatcher_t *this) +{ + FCGX_ShutdownPending(); + while (this->thread_count--) + { + pthread_cancel(this->threads[this->thread_count]); + pthread_join(this->threads[this->thread_count], NULL); + } + this->sessions->destroy_function(this->sessions, (void*)session_entry_destroy); + this->controllers->destroy_function(this->controllers, free); + free(this); +} + +/* + * see header file + */ +dispatcher_t *dispatcher_create(context_constructor_t constructor, void *param) +{ + private_dispatcher_t *this = malloc_thing(private_dispatcher_t); + + this->public.add_controller = (void(*)(dispatcher_t*, controller_constructor_t, void*))add_controller; + this->public.run = (void(*)(dispatcher_t*, int threads))run; + this->public.waitsignal = (void(*)(dispatcher_t*))waitsignal; + this->public.destroy = (void(*)(dispatcher_t*))destroy; + + this->sessions = linked_list_create(); + this->controllers = linked_list_create(); + this->context_constructor = constructor; + pthread_mutex_init(&this->mutex, NULL); + this->param = param; + this->fd = 0; + this->timeout = 180; + + FCGX_Init(); + +#ifdef FCGI_SOCKET + unlink(FCGI_SOCKET); + this->fd = FCGX_OpenSocket(FCGI_SOCKET, 10); +#endif /* FCGI_SOCKET */ + + return &this->public; +} + diff --git a/src/manager/lib/dispatcher.h b/src/manager/lib/dispatcher.h new file mode 100644 index 000000000..5119a1eab --- /dev/null +++ b/src/manager/lib/dispatcher.h @@ -0,0 +1,78 @@ +/** + * @file dispatcher.h + * + * @brief Interface of dispatcher_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DISPATCHER_H_ +#define DISPATCHER_H_ + +#include "controller.h" + +typedef struct dispatcher_t dispatcher_t; + +/** + * @brief Dispatcher, accepts connections using multiple threads. + * + * The dispatcher creates a session for each client (using SID cookies). In + * each session, a session context is created using the context constructor. + * Each controller is instanciated in the session using the controller + * constructor added with add_controller. + */ +struct dispatcher_t { + + /** + * @brief Register a controller to the dispatcher. + * + * @param constructor constructor function to the conntroller + * @param param param to pass to constructor + */ + void (*add_controller)(dispatcher_t *this, + controller_constructor_t constructor, void *param); + + /** + * @brief Start with dispatching. + * + * @param thread number of dispatching threads + */ + void (*run)(dispatcher_t *this, int threads); + + /** + * @brief Wait for a relevant signal action. + */ + void (*waitsignal)(dispatcher_t *this); + + /** + * @brief Destroy the dispatcher_t. + */ + void (*destroy) (dispatcher_t *this); +}; + +/** + * @brief Create a dispatcher. + * + * The context constructor is invoked to create a session context for + * each session. + * + * @param constructor construction function for session context + * @param param parameter to supply to context constructor + */ +dispatcher_t *dispatcher_create(context_constructor_t constructor, void *param); + +#endif /* DISPATCHER_H_ */ diff --git a/src/manager/lib/enumerator.h b/src/manager/lib/enumerator.h new file mode 100644 index 000000000..de272f9c9 --- /dev/null +++ b/src/manager/lib/enumerator.h @@ -0,0 +1,49 @@ +/** + * @file enumerator.h + * + * @brief Interface of enumerator_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct enumerator_t enumerator_t; + +/** + * @brief Enumerate is simpler, but more flexible than iterator. + */ +struct enumerator_t { + + /** + * @brief Enumerate collection. + * + * @param ... variable argument list of pointers, NULL terminated + * @return TRUE if pointers returned + */ + bool (*enumerate)(enumerator_t *this, ...); + + /** + * @brief Destroy a enumerator instance. + */ + void (*destroy)(enumerator_t *this); +}; + +#endif /* ENUMERATOR_H_ */ diff --git a/src/manager/lib/request.c b/src/manager/lib/request.c new file mode 100644 index 000000000..2e12d3643 --- /dev/null +++ b/src/manager/lib/request.c @@ -0,0 +1,306 @@ +/** + * @file request.c + * + * @brief Implementation of request_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +#include + +typedef struct { + char *name; + char *value; +} name_value_t; + +/** + * destroy a name value pair + */ +static void name_value_destroy(name_value_t *this) +{ + free(this->name); + free(this->value); + free(this); +} + +typedef struct private_request_t private_request_t; + +/** + * private data of the task manager + */ +struct private_request_t { + + /** + * public functions + */ + request_t public; + + /** + * the associated fcgi request + */ + FCGX_Request *req; + + /** + * list of cookies (name_value_t) + */ + linked_list_t *cookies; + + /** + * list of post data (name_value_t) + */ + linked_list_t *posts; +}; + +/** + * Implementation of request_t.get_cookie. + */ +static char* get_cookie(private_request_t *this, char *name) +{ + char *value = NULL; + name_value_t *cookie; + iterator_t *iterator; + + iterator = this->cookies->create_iterator(this->cookies, TRUE); + while (iterator->iterate(iterator, (void**)&cookie)) + { + if (streq(cookie->name, name)) + { + value = cookie->value; + break; + } + } + iterator->destroy(iterator); + return value; +} + +/** + * Implementation of request_t.get_path. + */ +static char* get_path(private_request_t *this) +{ + char * path = FCGX_GetParam("PATH_INFO", this->req->envp); + return path ? path : ""; +} + +/** + * Implementation of request_t.get_post_data. + */ +static char* get_post_data(private_request_t *this, char *name) +{ + char *value = NULL; + name_value_t *data; + iterator_t *iterator; + + iterator = this->posts->create_iterator(this->posts, TRUE); + while (iterator->iterate(iterator, (void**)&data)) + { + if (streq(data->name, name)) + { + value = data->value; + break; + } + } + iterator->destroy(iterator); + return value; +} + +/** + * convert 2 digit hex string to a integer + */ +static char hex2char(char *hex) +{ + static char hexdig[] = "00112233445566778899AaBbCcDdEeFf"; + + return (strchr(hexdig, hex[1]) - hexdig)/2 + + ((strchr(hexdig, hex[0]) - hexdig)/2 * 16); +} + +/** + * unescape a string up to the delimiter, and return a clone + */ +static char *unescape(char **pos, char delimiter) +{ + char *ptr, *res, *end, code[3] = {'\0','\0','\0'}; + + if (**pos == '\0') + { + return NULL; + } + ptr = strchr(*pos, delimiter); + if (ptr) + { + res = strndup(*pos, ptr - *pos); + *pos = ptr + 1; + } + else + { + res = strdup(*pos); + *pos = ""; + } + end = res + strlen(res) + 1; + /* replace '+' with ' ' */ + ptr = res; + while ((ptr = strchr(ptr, '+'))) + { + *ptr = ' '; + } + /* replace %HH with its ascii value */ + ptr = res; + while ((ptr = strchr(ptr, '%'))) + { + if (ptr > end - 2) + { + break; + } + strncpy(code, ptr + 1, 2); + *ptr = hex2char(code); + memmove(ptr + 1, ptr + 3, end - (ptr + 3)); + } + return res; +} + +/** + * parse the http POST data + */ +static void parse_post(private_request_t *this) +{ + char buf[4096], *pos, *name, *value; + name_value_t *data; + int len; + + if (!streq(FCGX_GetParam("REQUEST_METHOD", this->req->envp), "POST") || + !streq(FCGX_GetParam("CONTENT_TYPE", this->req->envp), + "application/x-www-form-urlencoded")) + { + return; + } + + len = FCGX_GetStr(buf, sizeof(buf) - 1, this->req->in); + if (len != atoi(FCGX_GetParam("CONTENT_LENGTH", this->req->envp))) + { + return; + } + buf[len] = 0; + + pos = buf; + while (TRUE) + { + name = unescape(&pos, '='); + if (name) + { + value = unescape(&pos, '&'); + if (value) + { + data = malloc_thing(name_value_t); + data->name = name; + data->value = value; + this->posts->insert_last(this->posts, data); + continue; + } + else + { + free(name); + } + } + break; + } +} + +/** + * parse the requests cookies + */ +static void parse_cookies(private_request_t *this) +{ + char *str, *pos; + name_value_t *cookie; + + str = FCGX_GetParam("HTTP_COOKIE", this->req->envp); + while (str) + { + if (*str == ' ') + { + str++; + continue; + } + pos = strchr(str, '='); + if (pos == NULL) + { + break; + } + cookie = malloc_thing(name_value_t); + cookie->name = strndup(str, pos - str); + cookie->value = NULL; + str = pos + 1; + if (str) + { + pos = strchr(str, ';'); + if (pos) + { + cookie->value = strndup(str, pos - str); + } + else + { + cookie->value = strdup(str); + } + } + this->cookies->insert_last(this->cookies, cookie); + if (pos == NULL) + { + break; + } + str = pos + 1; + } +} + +/** + * Implementation of request_t.destroy + */ +static void destroy(private_request_t *this) +{ + this->cookies->destroy_function(this->cookies, (void*)name_value_destroy); + this->posts->destroy_function(this->posts, (void*)name_value_destroy); + free(this); +} + +/* + * see header file + */ +request_t *request_create(FCGX_Request *request) +{ + private_request_t *this = malloc_thing(private_request_t); + + this->public.get_path = (char*(*)(request_t*))get_path; + this->public.get_cookie = (char*(*)(request_t*,char*))get_cookie; + this->public.get_post_data = (char*(*)(request_t*, char *name))get_post_data; + this->public.destroy = (void(*)(request_t*))destroy; + + this->req = request; + this->cookies = linked_list_create(); + this->posts = linked_list_create(); + + parse_cookies(this); + parse_post(this); + + return &this->public; +} + diff --git a/src/manager/lib/request.h b/src/manager/lib/request.h new file mode 100644 index 000000000..852238a1d --- /dev/null +++ b/src/manager/lib/request.h @@ -0,0 +1,73 @@ +/** + * @file request.h + * + * @brief Interface of request_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct request_t request_t; + +/** + * @brief A HTTP request, encapsulates FCGX_Request. + * + */ +struct request_t { + + /** + * @brief Get a cookie the client sent in the request. + * + * @param name name of the cookie + * @return cookie value, NULL if no such cookie found + */ + char* (*get_cookie)(request_t *this, char *name); + + /** + * @brief Get the request path relative to the application. + * + * @return path + */ + char* (*get_path)(request_t *this); + + /** + * @brief Get a post variable included in the request. + * + * @param name name of the POST variable + * @return value, NULL if not found + */ + char* (*get_post_data)(request_t *this, char *name); + + /** + * @brief Destroy the request_t. + */ + void (*destroy) (request_t *this); +}; + +/** + * @brief Create a request from the fastcgi struct. + * + * @param request the FCGI request + */ +request_t *request_create(FCGX_Request *request); + +#endif /* REQUEST_H_ */ diff --git a/src/manager/lib/response.c b/src/manager/lib/response.c new file mode 100644 index 000000000..ae74ab6e5 --- /dev/null +++ b/src/manager/lib/response.c @@ -0,0 +1,223 @@ +/** + * @file response.c + * + * @brief Implementation of response_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 +#include + +#include + +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**)¤t)) + { + 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**)¤t)) + { + FCGX_FPrintF(this->req->out, "%s: %s\n", + current->name, current->value); + } + iterator->destroy(iterator); + FCGX_PutChar('\n', this->req->out); + this->started = TRUE; +} + +/** + * Implementation of response_t.print. + */ +static void print_(private_response_t *this, char *str) +{ + if (!this->started) + { + write_headers(this); + } + FCGX_PutS(str, this->req->out); +} + +/** + * Implementation of response_t.printf. + */ +static void printf_(private_response_t *this, char *format, ...) +{ + va_list args; + + if (!this->started) + { + write_headers(this); + } + + va_start(args, format); + FCGX_VFPrintF(this->req->out, format, args); + va_end(args); +} + +/** + * Implementation of response_t.add_header. + */ +static void add_header(private_response_t *this, char *name, char *value) +{ + this->headers->insert_last(this->headers, name_value_create(name, value)); +} + +/** + * Implementation of response_t.set_content_type. + */ +static void set_content_type(private_response_t *this, char *type) +{ + free(this->content_type); + this->content_type = strdup(type); +} + +/** + * Implementation of response_t.add_cookie. + */ +static void add_cookie(private_response_t *this, char *name, char *value) +{ + this->cookies->insert_last(this->cookies, name_value_create(name, value)); +} + +/** + * Implementation of response_t.redirect. + */ +static void redirect(private_response_t *this, char *location) +{ + FCGX_FPrintF(this->req->out, "Status: 303 See Other\n"); + FCGX_FPrintF(this->req->out, "Location: %s%s%s\n\n", + FCGX_GetParam("SCRIPT_NAME", this->req->envp), + *location == '/' ? "" : "/", location); +} + +/** + * Implementation of response_t.destroy + */ +static void destroy(private_response_t *this) +{ + this->headers->destroy_function(this->headers, (void*)name_value_destroy); + this->cookies->destroy_function(this->cookies, (void*)name_value_destroy); + free(this->content_type); + free(this); +} + +/* + * see header file + */ +response_t *response_create(FCGX_Request *request) +{ + private_response_t *this = malloc_thing(private_response_t); + + this->public.print = (void(*)(response_t*, char *str))print_; + this->public.printf = (void(*)(response_t*, char *format, ...))printf_; + this->public.add_header = (void(*)(response_t*, char *name, char *value))add_header; + this->public.set_content_type = (void(*)(response_t*, char *type))set_content_type; + this->public.add_cookie = (void(*)(response_t*, char *name, char *value))add_cookie; + this->public.redirect = (void(*)(response_t*, char *location))redirect; + this->public.destroy = (void(*)(response_t*))destroy; + + this->req = request; + this->headers = linked_list_create(); + this->cookies = linked_list_create(); + this->content_type = strdup("text/html"); + this->started = FALSE; + + return &this->public; +} + diff --git a/src/manager/lib/response.h b/src/manager/lib/response.h new file mode 100644 index 000000000..e3be2cf43 --- /dev/null +++ b/src/manager/lib/response.h @@ -0,0 +1,95 @@ +/** + * @file response.h + * + * @brief Interface of response_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct response_t response_t; + +/** + * @brief A HTTP response, wraps response functionality around FCGX_Request. + * + */ +struct response_t { + + /** + * @brief Write a string to the client. + * + * @param str string to write + */ + void (*print)(response_t *this, char *str); + + /** + * @brief Write a printf like format string to client. + * + * @param format printf like format string + * @param ... variable argument list + */ + void (*printf)(response_t *this, char *format, ...); + + /** + * @brief Add a custom header to the response. + * + * @param name name of the header + * @param value value of the header + */ + void (*add_header)(response_t *this, char *name, char *value); + + /** + * @brief Set the content type (Content-Type header). + * + * @param type content type (e.g. text/html) + */ + void (*set_content_type)(response_t *this, char *type); + + /** + * @brief Add a cookie to the response (Set-Cookie header). + * + * @param name name of the cookie to set + * @param value value of the cookie + */ + void (*add_cookie)(response_t *this, char *name, char *value); + + /** + * @brief Redirect the client to another location. + * + * @param location location to redirect to + */ + void (*redirect)(response_t *this, char *location); + + /** + * @brief Destroy a response_t. + */ + void (*destroy) (response_t *this); +}; + +/** + * @brief Create a response. + * + * @param request the FCGI request structure + */ +response_t *response_create(FCGX_Request *request); + +#endif /* RESPONSE_H_ */ diff --git a/src/manager/lib/session.c b/src/manager/lib/session.c new file mode 100644 index 000000000..be25f2737 --- /dev/null +++ b/src/manager/lib/session.c @@ -0,0 +1,185 @@ +/** + * @file session.c + * + * @brief Implementation of session_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 +#include +#include + +#include +#include + +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**)¤t)) + { + 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, "

Not Found

\n"); + } +} + +/** + * Implementation of session_t.get_sid. + */ +static char* get_sid(private_session_t *this) +{ + return this->sid; +} + +/** + * Implementation of session_t.destroy + */ +static void destroy(private_session_t *this) +{ + this->controllers->destroy_offset(this->controllers, offsetof(controller_t, destroy)); + if (this->context) this->context->destroy(this->context); + free(this->sid); + free(this); +} + +/* + * see header file + */ +session_t *session_create(context_t *context) +{ + private_session_t *this = malloc_thing(private_session_t); + + this->public.add_controller = (void(*)(session_t*, controller_t*))add_controller; + this->public.process = (void(*)(session_t*, request_t*,response_t*))process; + this->public.get_sid = (char*(*)(session_t*))get_sid; + this->public.destroy = (void(*)(session_t*))destroy; + + this->sid = NULL; + this->controllers = linked_list_create(); + this->context = context; + + return &this->public; +} + diff --git a/src/manager/lib/session.h b/src/manager/lib/session.h new file mode 100644 index 000000000..baaacd098 --- /dev/null +++ b/src/manager/lib/session.h @@ -0,0 +1,75 @@ +/** + * @file session.h + * + * @brief Interface of session_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef SESSION_H_ +#define SESSION_H_ + +#include "request.h" +#include "response.h" +#include "controller.h" + +typedef struct session_t session_t; + +/** + * @brief A session, identified by a session ID. + * + */ +struct session_t { + + /** + * @brief Get the session ID of the session. + * + * @return session ID + */ + char* (*get_sid)(session_t *this); + + /** + * @brief Add a controller instance to the session. + * + * @param controller controller to add + */ + void (*add_controller)(session_t *this, controller_t *controller); + + /** + * @brief Process a request in this session. + * + * @param request request to process + * @param response response to send + */ + void (*process)(session_t *this, request_t *request, response_t *response); + + /** + * @brief Destroy the session_t. + * + * @param this calling object + */ + void (*destroy) (session_t *this); +}; + +/** + * @brief Create a session. + * + * @param context user defined session context instance + */ +session_t *session_create(context_t *context); + +#endif /* SESSION_H_ */ diff --git a/src/manager/lib/template.c b/src/manager/lib/template.c new file mode 100644 index 000000000..f168f9a56 --- /dev/null +++ b/src/manager/lib/template.c @@ -0,0 +1,138 @@ +/** + * @file template.c + * + * @brief Implementation of template_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +#include + +typedef struct private_template_t private_template_t; + +/** + * private data of the task manager + */ +struct private_template_t { + + /** + * public functions + */ + template_t public; + + /** + * template file + */ + char *file; + + /** + * clearsilver HDF dataset + */ + HDF *hdf; +}; + +/** + * clearsilver cs_render callback function + */ +static NEOERR* render_cb(response_t *response, char *str) +{ + response->print(response, str); + return NULL; +} + +/** + * Implementation of template_t.render. + */ +static void render(private_template_t *this, response_t *response) +{ + NEOERR* err; + CSPARSE *parse; + + hdf_remove_tree(this->hdf, ""); + + err = cs_init(&parse, this->hdf); + if (!err) + { + err = cs_parse_file(parse, this->file); + if (!err) + { + err = cs_render(parse, response, (CSOUTFUNC)render_cb); + if (!err) + { + cs_destroy(&parse); + return; + } + } + cs_destroy(&parse); + } + nerr_log_error(err); + return; +} + +/** + * Implementation of template_t.set. + */ +static void set(private_template_t *this, char *key, char *value) +{ + hdf_set_value(this->hdf, key, value); +} + +/** + * Implementation of template_t.setf. + */ +static void setf(private_template_t *this, char *format, ...) +{ + va_list args; + + va_start(args, format); + hdf_set_valuevf(this->hdf, format, args); + va_end(args); +} + +/** + * Implementation of template_t.destroy + */ +static void destroy(private_template_t *this) +{ + hdf_destroy(&this->hdf); + free(this->file); + free(this); +} + +/* + * see header file + */ +template_t *template_create(char *file) +{ + private_template_t *this = malloc_thing(private_template_t); + + this->public.render = (void(*)(template_t*,response_t*))render; + this->public.set = (void(*)(template_t*, char *, char*))set; + this->public.setf = (void(*)(template_t*, char *format, ...))setf; + this->public.destroy = (void(*)(template_t*))destroy; + + this->file = strdup(file); + this->hdf = NULL; + + hdf_init(&this->hdf); + return &this->public; +} + diff --git a/src/manager/lib/template.h b/src/manager/lib/template.h new file mode 100644 index 000000000..1a8c2f7b7 --- /dev/null +++ b/src/manager/lib/template.h @@ -0,0 +1,76 @@ +/** + * @file template.h + * + * @brief Interface of template_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef TEMPLATE_H_ +#define TEMPLATE_H_ + +#include "response.h" + +typedef struct template_t template_t; + +/** + * @brief Template engine based on ClearSilver. + * + */ +struct template_t { + + /** + * @brief Set a template value. + * + * @param key key to set + * @param value value to set key to + */ + void (*set)(template_t *this, char *key, char *value); + + /** + * @brief Set a template value using format strings. + * + * Format string is in the form "key=value", where printf like format + * substitution occurs over the whole string. + * + * @param format printf like format string + * @param ... variable argument list + */ + void (*setf)(template_t *this, char *format, ...); + + /** + * @brief Render a template to a response object. + * + * @param response response to render to + * @return rendered template string + */ + void (*render)(template_t *this, response_t *response); + + /** + * @brief Destroy the template_t. + */ + void (*destroy) (template_t *this); +}; + +/** + * @brief Create a template from a file. + * + * @param file template file + */ +template_t *template_create(char *file); + +#endif /* TEMPLATE_H_ */ diff --git a/src/manager/main.c b/src/manager/main.c new file mode 100644 index 000000000..5aec02156 --- /dev/null +++ b/src/manager/main.c @@ -0,0 +1,62 @@ +/** + * @file main.c + * + * @brief Implementation of dispatcher_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 +#include + +#include "manager.h" +#include "database.h" +#include "controller/static_controller.h" +#include "controller/auth_controller.h" +#include "controller/status_controller.h" +#include "controller/gateway_controller.h" + +#define DBFILE "/usr/local/libexec/ipsec/sqlite.db" + +int main (int arc, char *argv[]) +{ + dispatcher_t *dispatcher; + database_t *database; + + database = database_create(DBFILE); + if (database == NULL) + { + fprintf(stderr, "opening database '%s' failed.\n", DBFILE); + return 1; + } + + dispatcher = dispatcher_create((context_constructor_t)manager_create, database); + + dispatcher->add_controller(dispatcher, static_controller_create, NULL); + dispatcher->add_controller(dispatcher, auth_controller_create, NULL); + dispatcher->add_controller(dispatcher, status_controller_create, NULL); + dispatcher->add_controller(dispatcher, gateway_controller_create, NULL); + + dispatcher->run(dispatcher, 10); + + dispatcher->waitsignal(dispatcher); + + dispatcher->destroy(dispatcher); + database->destroy(database); + + return 0; +} diff --git a/src/manager/manager.c b/src/manager/manager.c new file mode 100644 index 000000000..dc27f86a6 --- /dev/null +++ b/src/manager/manager.c @@ -0,0 +1,160 @@ +/** + * @file manager.c + * + * @brief Implementation of manager_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +typedef struct private_manager_t private_manager_t; + +/** + * private data of manager + */ +struct private_manager_t { + + /** + * public functions + */ + manager_t public; + + /** + * underlying database + */ + database_t *db; + + /** + * user id, if we are logged in + */ + int user; + + /** + * selected gateway + */ + gateway_t *gateway; +}; + +/** + * Implementation of manager_t.create_gateway_enumerator. + */ +static enumerator_t* create_gateway_enumerator(private_manager_t *this) +{ + return this->db->create_gateway_enumerator(this->db, this->user); +} + +/** + * Implementation of manager_t.select_gateway. + */ +static gateway_t* select_gateway(private_manager_t *this, int select_id) +{ + if (select_id != 0) + { + enumerator_t *enumerator; + int id, port; + char *name, *address; + host_t *host; + + if (this->gateway) this->gateway->destroy(this->gateway); + this->gateway = NULL; + + enumerator = this->db->create_gateway_enumerator(this->db, this->user); + while (enumerator->enumerate(enumerator, &id, &name, &port, &address)) + { + if (select_id == id) + { + if (port != 0) + { + host = host_create_from_string(address, port); + if (host) + { + this->gateway = gateway_create(name, host); + } + } + break; + } + } + enumerator->destroy(enumerator); + } + return this->gateway; +} + +/** + * Implementation of manager_t.logged_in. + */ +static bool logged_in(private_manager_t *this) +{ + return this->user != 0; +} + +/** + * Implementation of manager_t.login. + */ +static bool login(private_manager_t *this, char *username, char *password) +{ + if (!this->user) + { + this->user = this->db->login(this->db, username, password); + } + return this->user != 0; +} + +/** + * Implementation of manager_t.logout. + */ +static void logout(private_manager_t *this) +{ + this->user = 0; + this->gateway->destroy(this->gateway); + this->gateway = NULL; +} + +/** + * Implementation of manager_t.destroy + */ +static void destroy(private_manager_t *this) +{ + if (this->gateway) this->gateway->destroy(this->gateway); + free(this); +} + +/* + * see header file + */ +manager_t *manager_create(database_t *database) +{ + private_manager_t *this = malloc_thing(private_manager_t); + + this->public.login = (bool(*)(manager_t*, char *username, char *password))login; + this->public.logged_in = (bool(*)(manager_t*))logged_in; + this->public.logout = (void(*)(manager_t*))logout; + this->public.create_gateway_enumerator = (enumerator_t*(*)(manager_t*))create_gateway_enumerator; + this->public.select_gateway = (gateway_t*(*)(manager_t*, int id))select_gateway; + this->public.context.destroy = (void(*)(context_t*))destroy; + + this->user = 0; + this->db = database; + this->gateway = NULL; + + return &this->public; +} + diff --git a/src/manager/manager.h b/src/manager/manager.h new file mode 100644 index 000000000..4235618cd --- /dev/null +++ b/src/manager/manager.h @@ -0,0 +1,93 @@ +/** + * @file manager.h + * + * @brief Interface of manager_t. + * + */ + +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * 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 + +#include + +typedef struct manager_t manager_t; + +/** + * @brief The manager, manages multiple gateways. + */ +struct manager_t { + + /** + * implements context_t interface + */ + context_t context; + + /** + * @brief Create an iterator over all configured gateways. + * + * enumerate() arguments: int id, char *name, int port, char *address + * If port is 0, address is a Unix socket address. + * + * @return enumerator + */ + enumerator_t* (*create_gateway_enumerator)(manager_t *this); + + /** + * @brief Select a gateway. + * + * If id is 0, the previously selected gateway is returned. If none has + * been selected yet, NULL is returned. + * + * @param id id of the gateway (from enumerate), or 0 + * @return selected gateway, or NULL + */ + gateway_t* (*select_gateway)(manager_t *this, int id); + + /** + * @brief Try to log in. + * + * @param username username + * @param password cleartext password + * @return TRUE if login successful + */ + bool (*login)(manager_t *this, char *username, char *password); + + /** + * @brief Check if user logged in. + * + * @return TRUE if logged in + */ + bool (*logged_in)(manager_t *this); + + /** + * @brief Log out. + */ + void (*logout)(manager_t *this); +}; + +/** + * @brief Create a manager instance. + */ +manager_t *manager_create(database_t *database); + +#endif /* MANAGER_H_ */ diff --git a/src/manager/templates/auth/login.cs b/src/manager/templates/auth/login.cs new file mode 100644 index 000000000..f84c6307c --- /dev/null +++ b/src/manager/templates/auth/login.cs @@ -0,0 +1,15 @@ + +
+ + + + + + + + + + +
Username
Password
+
+ diff --git a/src/manager/templates/auth/logout.cs b/src/manager/templates/auth/logout.cs new file mode 100644 index 000000000..e69de29bb diff --git a/src/manager/templates/footer.cs b/src/manager/templates/footer.cs new file mode 100644 index 000000000..b605728ee --- /dev/null +++ b/src/manager/templates/footer.cs @@ -0,0 +1,2 @@ + + diff --git a/src/manager/templates/gateway/list.cs b/src/manager/templates/gateway/list.cs new file mode 100644 index 000000000..5cc8603b1 --- /dev/null +++ b/src/manager/templates/gateway/list.cs @@ -0,0 +1,13 @@ + +
+

+ +

+ +

+

+ diff --git a/src/manager/templates/header.cs b/src/manager/templates/header.cs new file mode 100644 index 000000000..b417ef916 --- /dev/null +++ b/src/manager/templates/header.cs @@ -0,0 +1,8 @@ + + + + + strongSwan management + + diff --git a/src/manager/templates/static/style.css b/src/manager/templates/static/style.css new file mode 100644 index 000000000..986ae066e --- /dev/null +++ b/src/manager/templates/static/style.css @@ -0,0 +1,188 @@ +html { + height:100%; + width: auto; + margin:0; + padding:0; +} + + +body { + font-family: Verdana, Helvetica, sans-serif; + font-size: 12px; + width: 100%; + height:100%; + margin:0; + padding:0; + background-color: #EEEEEE; +} + +h1 { + color: #203781; + font-size: 18px; + font-weight: bold; +} + +h2 { + color: #203781; + font-size: 17px; + font-weight: bold; +} + +h3 { + color: #203781; + font-size: 16px; + font-weight: bold; +} + +h4 { + color: #203781; + font-size: 15px; + font-weight: bold; +} + +p { + line-height: 1.2; + font-size: 11px; +} + +a { + color: black; + font-size: 12px; +} + +#headermain { + min-height: 100%; + background-color: white; + margin-left: 188px; +} + +/* ##### Header ##### */ + +#header { + width: 100%; + height: 30px; + background-color: #EEEEEE; +} + +.gatewayname{ + padding-top: 5px; + padding-left: 30px; + font-size: 12px; +} + +/* ##### Left Side Bar ##### */ + +.leftSideBar { + padding-top: 30px; + padding-left: 8px; + padding-right: 8px; + width: 170px; + float: left; +} + +.leftSideBar .sideBarTitle { + color: black; + font-weight: bold; + font-size: 12px; + margin: 0.1ex 0 0.1ex 0; +} + +.leftSideBar a { + color: #203781; + text-decoration: none; + display: block; + margin: 0; + padding: 0.8ex 1ex; +} + +.leftSideBar a:hover { + color: black; + background-color: lightgrey; + text-decoration: none; +} + +/* ##### Main ##### */ + +#main { + padding-top: 10px; + padding-left: 30px; + color: black; + text-align: justify; + line-height: 1.5em; +} + +/* ##### From Selection ##### */ + +.formbody { + background-color: white; + height: auto; +} + +.formbox { + width: 492px; + margin-top: 100px; + margin-left: auto; + margin-right: auto; + border-color: #333; + border-width: 1px; + border-style: solid; + padding: 10px; +} + +.formselection { + background-color: #EEEEEE; + border-color: #333; + border-width: 1px; + border-style: solid; +} + +.selection { + background-color: white; + border-color: #333; + border-style: solid; + margin-left: 12px; + margin-right: 4px; + border-width: 1px; + width: 400px; +} + +.button { + font-size: 12px; + font-weight: bold; + width: 50px; + border-color: #333; + border-width: 1px; + border-style: solid; + background-color: lightgrey; +} + +.message { + color: red; +} + +/* ##### Tables ##### */ + +th { + padding-right: 15px; +} + +td { + padding-right: 15px; +} + +/* ##### Lists ##### */ + +ul { + list-style: None; + padding-left: 0; +} + +li { + padding-bottom: 5px; +} + +/* ##### Labels ##### */ + +label { + font-weight: bold; +} \ No newline at end of file diff --git a/src/manager/templates/status/ikesalist.cs b/src/manager/templates/status/ikesalist.cs new file mode 100644 index 000000000..f9becf8d0 --- /dev/null +++ b/src/manager/templates/status/ikesalist.cs @@ -0,0 +1 @@ +