first revision of new manager webapp
This commit is contained in:
parent
f0c156fbc9
commit
965e99b5bf
|
@ -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 ?>
|
Loading…
Reference in New Issue