first revision of new manager webapp
This commit is contained in:
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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_ */
|
||||||
@@ -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_ */
|
||||||
@@ -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**)¤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, "<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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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_ */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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**)¤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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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**)¤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, "<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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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" ?>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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" ?>
|
||||||
@@ -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>
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<?cs var:xml ?>
|
||||||
Reference in New Issue
Block a user