ipseclib_LTLIBRARIES = libfast.la
libfast_la_SOURCES = \
- dispatcher.c request.c session.c smtp.c
+ fast_dispatcher.c fast_request.c fast_session.c fast_smtp.c
if USE_DEV_HEADERS
fast_includedir = ${dev_headers}/fast
nobase_fast_include_HEADERS = \
- context.h controller.h dispatcher.h filter.h request.h session.h smtp.h
+ fast_context.h fast_controller.h fast_dispatcher.h fast_filter.h \
+ fast_request.h fast_session.h fast_smtp.h
endif
libfast_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
+++ /dev/null
-/*
- * 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.
- */
-
-/**
- * @defgroup context context
- * @{ @ingroup libfast
- */
-
-#ifndef CONTEXT_H_
-#define CONTEXT_H_
-
-typedef struct context_t context_t;
-
-/**
- * Constructor function for a user specific context.
- */
-typedef context_t *(*context_constructor_t)(void *param);
-
-/**
- * User specific session context, to extend.
- */
-struct context_t {
-
- /**
- * Destroy the context_t.
- */
- void (*destroy) (context_t *this);
-};
-
-#endif /** CONTEXT_H_ @}*/
+++ /dev/null
-/*
- * 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.
- */
-
-/**
- * @defgroup controller controller
- * @{ @ingroup libfast
- */
-
-#ifndef CONTROLLER_H_
-#define CONTROLLER_H_
-
-#include "request.h"
-#include "context.h"
-
-typedef struct controller_t controller_t;
-
-/**
- * Constructor function for a controller.
- *
- * @param context session specific context, implements context_t
- * @param param user supplied param, as registered to the dispatcher
- */
-typedef controller_t *(*controller_constructor_t)(context_t* context, void *param);
-
-/**
- * Controller interface, to be implemented by users controllers.
- *
- * Controller instances get created per session, so each session has an
- * associated set of private controller instances.
- * The controller handle function is called for each incoming request.
- */
-struct controller_t {
-
- /**
- * Get the name of the controller.
- *
- * @return name of the controller
- */
- char* (*get_name)(controller_t *this);
-
- /**
- * Handle a HTTP request for that controller.
- *
- * Request URLs are parsed in the form
- * controller_name/p1/p2/p3/p4/p5 with a maximum of 5 parameters. Each
- * parameter not found in the request URL is set to NULL.
- *
- * @param request HTTP request
- * @param p1 first parameter
- * @param p2 second parameter
- * @param p3 third parameter
- * @param p4 forth parameter
- * @param p5 fifth parameter
- * @return
- */
- void (*handle)(controller_t *this, request_t *request,
- char *p1, char *p2, char *p3, char *p4, char *p5);
-
- /**
- * Destroy the controller instance.
- */
- void (*destroy) (controller_t *this);
-};
-
-#endif /** CONTROLLER_H_ @}*/
+++ /dev/null
-/*
- * 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 <signal.h>
-#include <unistd.h>
-
-#include <utils/debug.h>
-#include <threading/thread.h>
-#include <threading/condvar.h>
-#include <threading/mutex.h>
-#include <collections/linked_list.h>
-#include <collections/hashtable.h>
-
-/** Intervall to check for expired sessions, in seconds */
-#define CLEANUP_INTERVAL 30
-
-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
- */
- thread_t **threads;
-
- /**
- * number of threads in "threads"
- */
- int thread_count;
-
- /**
- * session locking mutex
- */
- mutex_t *mutex;
-
- /**
- * Hahstable with active sessions
- */
- hashtable_t *sessions;
-
- /**
- * session timeout
- */
- time_t timeout;
-
- /**
- * timestamp of last session cleanup round
- */
- time_t last_cleanup;
-
- /**
- * running in debug mode?
- */
- bool debug;
-
- /**
- * List of controllers controller_constructor_t
- */
- linked_list_t *controllers;
-
- /**
- * List of filters filter_constructor_t
- */
- linked_list_t *filters;
-
- /**
- * constructor function to create session context (in controller_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;
-} controller_entry_t;
-
-typedef struct {
- /** constructor function */
- filter_constructor_t constructor;
- /** parameter to constructor */
- void *param;
-} filter_entry_t;
-
-typedef struct {
- /** session instance */
- session_t *session;
- /** condvar to wait for session */
- condvar_t *cond;
- /** client host address, to prevent session hijacking */
- char *host;
- /** TRUE if session is in use */
- bool in_use;
- /** last use of the session */
- time_t used;
- /** has the session been closed by the handler? */
- bool closed;
-} session_entry_t;
-
-/**
- * create a session and instanciate controllers
- */
-static session_t* load_session(private_dispatcher_t *this)
-{
- enumerator_t *enumerator;
- controller_entry_t *centry;
- filter_entry_t *fentry;
- session_t *session;
- context_t *context = NULL;
- controller_t *controller;
- filter_t *filter;
-
- if (this->context_constructor)
- {
- context = this->context_constructor(this->param);
- }
- session = session_create(context);
-
- enumerator = this->controllers->create_enumerator(this->controllers);
- while (enumerator->enumerate(enumerator, ¢ry))
- {
- controller = centry->constructor(context, centry->param);
- session->add_controller(session, controller);
- }
- enumerator->destroy(enumerator);
-
- enumerator = this->filters->create_enumerator(this->filters);
- while (enumerator->enumerate(enumerator, &fentry))
- {
- filter = fentry->constructor(context, fentry->param);
- session->add_filter(session, filter);
- }
- enumerator->destroy(enumerator);
-
- return session;
-}
-
-/**
- * create a new session entry
- */
-static session_entry_t *session_entry_create(private_dispatcher_t *this,
- char *host)
-{
- session_entry_t *entry;
- session_t *session;
-
- session = load_session(this);
- if (!session)
- {
- return NULL;
- }
- INIT(entry,
- .cond = condvar_create(CONDVAR_TYPE_DEFAULT),
- .session = session,
- .host = strdup(host),
- .used = time_monotonic(NULL),
- );
- return entry;
-}
-
-/**
- * destroy a session
- */
-static void session_entry_destroy(session_entry_t *entry)
-{
- entry->session->destroy(entry->session);
- entry->cond->destroy(entry->cond);
- free(entry->host);
- free(entry);
-}
-
-METHOD(dispatcher_t, add_controller, void,
- private_dispatcher_t *this, controller_constructor_t constructor,
- void *param)
-{
- controller_entry_t *entry;
-
- INIT(entry,
- .constructor = constructor,
- .param = param,
- );
- this->controllers->insert_last(this->controllers, entry);
-}
-
-METHOD(dispatcher_t, add_filter, void,
- private_dispatcher_t *this, filter_constructor_t constructor, void *param)
-{
- filter_entry_t *entry;
-
- INIT(entry,
- .constructor = constructor,
- .param = param,
- );
- this->filters->insert_last(this->filters, entry);
-}
-
-/**
- * Hashtable hash function
- */
-static u_int session_hash(char *sid)
-{
- return chunk_hash(chunk_create(sid, strlen(sid)));
-}
-
-/**
- * Hashtable equals function
- */
-static bool session_equals(char *sid1, char *sid2)
-{
- return streq(sid1, sid2);
-}
-
-/**
- * Cleanup unused sessions
- */
-static void cleanup_sessions(private_dispatcher_t *this, time_t now)
-{
- if (this->last_cleanup < now - CLEANUP_INTERVAL)
- {
- char *sid;
- session_entry_t *entry;
- enumerator_t *enumerator;
- linked_list_t *remove;
-
- this->last_cleanup = now;
- remove = linked_list_create();
- enumerator = this->sessions->create_enumerator(this->sessions);
- while (enumerator->enumerate(enumerator, &sid, &entry))
- {
- /* check all sessions for timeout or close flag */
- if (!entry->in_use &&
- (entry->used < now - this->timeout || entry->closed))
- {
- remove->insert_last(remove, sid);
- }
- }
- enumerator->destroy(enumerator);
-
- while (remove->remove_last(remove, (void**)&sid) == SUCCESS)
- {
- entry = this->sessions->remove(this->sessions, sid);
- if (entry)
- {
- session_entry_destroy(entry);
- }
- }
- remove->destroy(remove);
- }
-}
-
-/**
- * Actual dispatching code
- */
-static void dispatch(private_dispatcher_t *this)
-{
- thread_cancelability(FALSE);
-
- while (TRUE)
- {
- request_t *request;
- session_entry_t *found = NULL;
- time_t now;
- char *sid;
-
- thread_cancelability(TRUE);
- request = request_create(this->fd, this->debug);
- thread_cancelability(FALSE);
-
- if (request == NULL)
- {
- continue;
- }
- now = time_monotonic(NULL);
- sid = request->get_cookie(request, "SID");
-
- this->mutex->lock(this->mutex);
- if (sid)
- {
- found = this->sessions->get(this->sessions, sid);
- }
- if (found && !streq(found->host, request->get_host(request)))
- {
- found = NULL;
- }
- if (found)
- {
- /* wait until session is unused */
- while (found->in_use)
- {
- found->cond->wait(found->cond, this->mutex);
- }
- }
- else
- { /* create a new session if not found */
- found = session_entry_create(this, request->get_host(request));
- if (!found)
- {
- request->destroy(request);
- this->mutex->unlock(this->mutex);
- continue;
- }
- sid = found->session->get_sid(found->session);
- this->sessions->put(this->sessions, sid, found);
- }
- found->in_use = TRUE;
- this->mutex->unlock(this->mutex);
-
- /* start processing */
- found->session->process(found->session, request);
- found->used = time_monotonic(NULL);
-
- /* release session */
- this->mutex->lock(this->mutex);
- found->in_use = FALSE;
- found->closed = request->session_closed(request);
- found->cond->signal(found->cond);
- cleanup_sessions(this, now);
- this->mutex->unlock(this->mutex);
-
- request->destroy(request);
- }
-}
-
-METHOD(dispatcher_t, run, void,
- private_dispatcher_t *this, int threads)
-{
- this->thread_count = threads;
- this->threads = malloc(sizeof(thread_t*) * threads);
- while (threads)
- {
- this->threads[threads - 1] = thread_create((thread_main_t)dispatch,
- this);
- if (this->threads[threads - 1])
- {
- threads--;
- }
- }
-}
-
-METHOD(dispatcher_t, waitsignal, void,
- 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);
-}
-
-METHOD(dispatcher_t, destroy, void,
- private_dispatcher_t *this)
-{
- char *sid;
- session_entry_t *entry;
- enumerator_t *enumerator;
-
- FCGX_ShutdownPending();
- while (this->thread_count--)
- {
- thread_t *thread = this->threads[this->thread_count];
- thread->cancel(thread);
- thread->join(thread);
- }
- enumerator = this->sessions->create_enumerator(this->sessions);
- while (enumerator->enumerate(enumerator, &sid, &entry))
- {
- session_entry_destroy(entry);
- }
- enumerator->destroy(enumerator);
- this->sessions->destroy(this->sessions);
- this->controllers->destroy_function(this->controllers, free);
- this->filters->destroy_function(this->filters, free);
- this->mutex->destroy(this->mutex);
- free(this->threads);
- free(this);
-}
-
-/*
- * see header file
- */
-dispatcher_t *dispatcher_create(char *socket, bool debug, int timeout,
- context_constructor_t constructor, void *param)
-{
- private_dispatcher_t *this;
-
- INIT(this,
- .public = {
- .add_controller = _add_controller,
- .add_filter = _add_filter,
- .run = _run,
- .waitsignal = _waitsignal,
- .destroy = _destroy,
- },
- .sessions = hashtable_create((void*)session_hash,
- (void*)session_equals, 4096),
- .controllers = linked_list_create(),
- .filters = linked_list_create(),
- .context_constructor = constructor,
- .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
- .param = param,
- .timeout = timeout,
- .last_cleanup = time_monotonic(NULL),
- .debug = debug,
- );
-
- FCGX_Init();
-
- if (socket)
- {
- unlink(socket);
- this->fd = FCGX_OpenSocket(socket, 10);
- }
- return &this->public;
-}
-
+++ /dev/null
-/*
- * 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.
- */
-
-/**
- * @defgroup libfast libfast
- * @{
- * FastCGI Application Server w/ templates.
- *
- * Libfast is a framework to write web applications in an MVC fashion. It uses
- * the ClearSilver template engine and communicates through FastCGI with
- * the webserver. It is multithreaded and really fast.
- *
- * The application has a global context and a session context. The global
- * context is accessed from all sessions simultaneously and therefore
- * needs to be threadsave. Often a database wrapper is the global context.
- * The session context is instanciated per session. Sessions are managed
- * automatically through session cookies. The session context is kept alive
- * until the session times out. It must implement the context_t interface and
- * a #context_constructor_t is needed to create instances. To each session,
- * a set of controllers gets instanciated. The controller instances are per
- * session, so you can hold private data for each user.
- * Controllers need to implement the controller_t interface and need a
- * #controller_constructor_t function to create instances.
- *
- * A small example shows how to set up libfast:
- * @code
- dispatcher_t *dispatcher;
- your_global_context_implementation_t *global;
-
- global = initialize_your_global_context();
-
- dispatcher = dispatcher_create(NULL, FALSE, 180,
- (context_constructor_t)your_session_context_create, global);
- dispatcher->add_controller(dispatcher, your_controller1_create, param1);
- dispatcher->add_controller(dispatcher, your_controller2_create, param2);
-
- dispatcher->run(dispatcher, 20);
-
- dispatcher->waitsignal(dispatcher);
-
- dispatcher->destroy(dispatcher);
- global->destroy();
- @endcode
- * @}
- *
- * @defgroup dispatcher dispatcher
- * @{ @ingroup libfast
- */
-
-#ifndef DISPATCHER_H_
-#define DISPATCHER_H_
-
-#include "controller.h"
-#include "filter.h"
-
-typedef struct dispatcher_t dispatcher_t;
-
-/**
- * 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 {
-
- /**
- * Register a controller to the dispatcher.
- *
- * The first controller added serves as default controller. Client's
- * get redirected to it if no other controller matches.
- *
- * @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);
-
- /**
- * Add a filter to the dispatcher.
- *
- * @param constructor constructor to create filter in session
- * @param param param to pass to constructor
- */
- void (*add_filter)(dispatcher_t *this,
- filter_constructor_t constructor, void *param);
-
- /**
- * Start with dispatching.
- *
- * Instanciate a constant thread pool and start dispatching requests.
- *
- * @param threads number of dispatching threads
- */
- void (*run)(dispatcher_t *this, int threads);
-
- /**
- * Wait for a relevant signal action.
- *
- */
- void (*waitsignal)(dispatcher_t *this);
-
- /**
- * Destroy the dispatcher_t.
- */
- void (*destroy) (dispatcher_t *this);
-};
-
-/**
- * Create a dispatcher.
- *
- * The context constructor is invoked to create a session context for
- * each session.
- *
- * @param socket FastCGI socket path, NULL for dynamic
- * @param debug no stripping, no compression, timing information
- * @param timeout session timeout
- * @param constructor construction function for session context
- * @param param parameter to supply to context constructor
- */
-dispatcher_t *dispatcher_create(char *socket, bool debug, int timeout,
- context_constructor_t constructor, void *param);
-
-#endif /** DISPATCHER_H_ @}*/
--- /dev/null
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup fast_context fast_context
+ * @{ @ingroup libfast
+ */
+
+#ifndef FAST_CONTEXT_H_
+#define FAST_CONTEXT_H_
+
+typedef struct fast_context_t fast_context_t;
+
+/**
+ * Constructor function for a user specific context.
+ */
+typedef fast_context_t *(*fast_context_constructor_t)(void *param);
+
+/**
+ * User specific session context, to extend.
+ */
+struct fast_context_t {
+
+ /**
+ * Destroy the fast_context_t.
+ */
+ void (*destroy) (fast_context_t *this);
+};
+
+#endif /** FAST_CONTEXT_H_ @}*/
--- /dev/null
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup fast_controller fast_controller
+ * @{ @ingroup libfast
+ */
+
+#ifndef FAST_CONTROLLER_H_
+#define FAST_CONTROLLER_H_
+
+#include "fast_request.h"
+#include "fast_context.h"
+
+typedef struct fast_controller_t fast_controller_t;
+
+/**
+ * Constructor function for a controller.
+ *
+ * @param context session specific context, implements context_t
+ * @param param user supplied param, as registered to the dispatcher
+ */
+typedef fast_controller_t *(*fast_controller_constructor_t)(
+ fast_context_t* context, void *param);
+
+/**
+ * Controller interface, to be implemented by users controllers.
+ *
+ * Controller instances get created per session, so each session has an
+ * associated set of private controller instances.
+ * The controller handle function is called for each incoming request.
+ */
+struct fast_controller_t {
+
+ /**
+ * Get the name of the controller.
+ *
+ * @return name of the controller
+ */
+ char* (*get_name)(fast_controller_t *this);
+
+ /**
+ * Handle a HTTP request for that controller.
+ *
+ * Request URLs are parsed in the form
+ * controller_name/p1/p2/p3/p4/p5 with a maximum of 5 parameters. Each
+ * parameter not found in the request URL is set to NULL.
+ *
+ * @param request HTTP request
+ * @param p1 first parameter
+ * @param p2 second parameter
+ * @param p3 third parameter
+ * @param p4 forth parameter
+ * @param p5 fifth parameter
+ * @return
+ */
+ void (*handle)(fast_controller_t *this, fast_request_t *request,
+ char *p1, char *p2, char *p3, char *p4, char *p5);
+
+ /**
+ * Destroy the controller instance.
+ */
+ void (*destroy) (fast_controller_t *this);
+};
+
+#endif /** FAST_CONTROLLER_H_ @}*/
--- /dev/null
+/*
+ * 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 "fast_dispatcher.h"
+
+#include "fast_request.h"
+#include "fast_session.h"
+
+#include <fcgiapp.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <utils/debug.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
+#include <collections/linked_list.h>
+#include <collections/hashtable.h>
+
+/** Intervall to check for expired sessions, in seconds */
+#define CLEANUP_INTERVAL 30
+
+typedef struct private_fast_dispatcher_t private_fast_dispatcher_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_fast_dispatcher_t {
+
+ /**
+ * public functions
+ */
+ fast_dispatcher_t public;
+
+ /**
+ * fcgi socket fd
+ */
+ int fd;
+
+ /**
+ * thread list
+ */
+ thread_t **threads;
+
+ /**
+ * number of threads in "threads"
+ */
+ int thread_count;
+
+ /**
+ * session locking mutex
+ */
+ mutex_t *mutex;
+
+ /**
+ * Hahstable with active sessions
+ */
+ hashtable_t *sessions;
+
+ /**
+ * session timeout
+ */
+ time_t timeout;
+
+ /**
+ * timestamp of last session cleanup round
+ */
+ time_t last_cleanup;
+
+ /**
+ * running in debug mode?
+ */
+ bool debug;
+
+ /**
+ * List of controllers controller_constructor_t
+ */
+ linked_list_t *controllers;
+
+ /**
+ * List of filters filter_constructor_t
+ */
+ linked_list_t *filters;
+
+ /**
+ * constructor function to create session context (in controller_entry_t)
+ */
+ fast_context_constructor_t context_constructor;
+
+ /**
+ * user param to context constructor
+ */
+ void *param;
+};
+
+typedef struct {
+ /** constructor function */
+ fast_controller_constructor_t constructor;
+ /** parameter to constructor */
+ void *param;
+} controller_entry_t;
+
+typedef struct {
+ /** constructor function */
+ fast_filter_constructor_t constructor;
+ /** parameter to constructor */
+ void *param;
+} filter_entry_t;
+
+typedef struct {
+ /** session instance */
+ fast_session_t *session;
+ /** condvar to wait for session */
+ condvar_t *cond;
+ /** client host address, to prevent session hijacking */
+ char *host;
+ /** TRUE if session is in use */
+ bool in_use;
+ /** last use of the session */
+ time_t used;
+ /** has the session been closed by the handler? */
+ bool closed;
+} session_entry_t;
+
+/**
+ * create a session and instanciate controllers
+ */
+static fast_session_t* load_session(private_fast_dispatcher_t *this)
+{
+ enumerator_t *enumerator;
+ controller_entry_t *centry;
+ filter_entry_t *fentry;
+ fast_session_t *session;
+ fast_context_t *context = NULL;
+ fast_controller_t *controller;
+ fast_filter_t *filter;
+
+ if (this->context_constructor)
+ {
+ context = this->context_constructor(this->param);
+ }
+ session = fast_session_create(context);
+
+ enumerator = this->controllers->create_enumerator(this->controllers);
+ while (enumerator->enumerate(enumerator, ¢ry))
+ {
+ controller = centry->constructor(context, centry->param);
+ session->add_controller(session, controller);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->filters->create_enumerator(this->filters);
+ while (enumerator->enumerate(enumerator, &fentry))
+ {
+ filter = fentry->constructor(context, fentry->param);
+ session->add_filter(session, filter);
+ }
+ enumerator->destroy(enumerator);
+
+ return session;
+}
+
+/**
+ * create a new session entry
+ */
+static session_entry_t *session_entry_create(private_fast_dispatcher_t *this,
+ char *host)
+{
+ session_entry_t *entry;
+ fast_session_t *session;
+
+ session = load_session(this);
+ if (!session)
+ {
+ return NULL;
+ }
+ INIT(entry,
+ .cond = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .session = session,
+ .host = strdup(host),
+ .used = time_monotonic(NULL),
+ );
+ return entry;
+}
+
+/**
+ * destroy a session
+ */
+static void session_entry_destroy(session_entry_t *entry)
+{
+ entry->session->destroy(entry->session);
+ entry->cond->destroy(entry->cond);
+ free(entry->host);
+ free(entry);
+}
+
+METHOD(fast_dispatcher_t, add_controller, void,
+ private_fast_dispatcher_t *this, fast_controller_constructor_t constructor,
+ void *param)
+{
+ controller_entry_t *entry;
+
+ INIT(entry,
+ .constructor = constructor,
+ .param = param,
+ );
+ this->controllers->insert_last(this->controllers, entry);
+}
+
+METHOD(fast_dispatcher_t, add_filter, void,
+ private_fast_dispatcher_t *this, fast_filter_constructor_t constructor,
+ void *param)
+{
+ filter_entry_t *entry;
+
+ INIT(entry,
+ .constructor = constructor,
+ .param = param,
+ );
+ this->filters->insert_last(this->filters, entry);
+}
+
+/**
+ * Hashtable hash function
+ */
+static u_int session_hash(char *sid)
+{
+ return chunk_hash(chunk_create(sid, strlen(sid)));
+}
+
+/**
+ * Hashtable equals function
+ */
+static bool session_equals(char *sid1, char *sid2)
+{
+ return streq(sid1, sid2);
+}
+
+/**
+ * Cleanup unused sessions
+ */
+static void cleanup_sessions(private_fast_dispatcher_t *this, time_t now)
+{
+ if (this->last_cleanup < now - CLEANUP_INTERVAL)
+ {
+ char *sid;
+ session_entry_t *entry;
+ enumerator_t *enumerator;
+ linked_list_t *remove;
+
+ this->last_cleanup = now;
+ remove = linked_list_create();
+ enumerator = this->sessions->create_enumerator(this->sessions);
+ while (enumerator->enumerate(enumerator, &sid, &entry))
+ {
+ /* check all sessions for timeout or close flag */
+ if (!entry->in_use &&
+ (entry->used < now - this->timeout || entry->closed))
+ {
+ remove->insert_last(remove, sid);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ while (remove->remove_last(remove, (void**)&sid) == SUCCESS)
+ {
+ entry = this->sessions->remove(this->sessions, sid);
+ if (entry)
+ {
+ session_entry_destroy(entry);
+ }
+ }
+ remove->destroy(remove);
+ }
+}
+
+/**
+ * Actual dispatching code
+ */
+static void dispatch(private_fast_dispatcher_t *this)
+{
+ thread_cancelability(FALSE);
+
+ while (TRUE)
+ {
+ fast_request_t *request;
+ session_entry_t *found = NULL;
+ time_t now;
+ char *sid;
+
+ thread_cancelability(TRUE);
+ request = fast_request_create(this->fd, this->debug);
+ thread_cancelability(FALSE);
+
+ if (request == NULL)
+ {
+ continue;
+ }
+ now = time_monotonic(NULL);
+ sid = request->get_cookie(request, "SID");
+
+ this->mutex->lock(this->mutex);
+ if (sid)
+ {
+ found = this->sessions->get(this->sessions, sid);
+ }
+ if (found && !streq(found->host, request->get_host(request)))
+ {
+ found = NULL;
+ }
+ if (found)
+ {
+ /* wait until session is unused */
+ while (found->in_use)
+ {
+ found->cond->wait(found->cond, this->mutex);
+ }
+ }
+ else
+ { /* create a new session if not found */
+ found = session_entry_create(this, request->get_host(request));
+ if (!found)
+ {
+ request->destroy(request);
+ this->mutex->unlock(this->mutex);
+ continue;
+ }
+ sid = found->session->get_sid(found->session);
+ this->sessions->put(this->sessions, sid, found);
+ }
+ found->in_use = TRUE;
+ this->mutex->unlock(this->mutex);
+
+ /* start processing */
+ found->session->process(found->session, request);
+ found->used = time_monotonic(NULL);
+
+ /* release session */
+ this->mutex->lock(this->mutex);
+ found->in_use = FALSE;
+ found->closed = request->session_closed(request);
+ found->cond->signal(found->cond);
+ cleanup_sessions(this, now);
+ this->mutex->unlock(this->mutex);
+
+ request->destroy(request);
+ }
+}
+
+METHOD(fast_dispatcher_t, run, void,
+ private_fast_dispatcher_t *this, int threads)
+{
+ this->thread_count = threads;
+ this->threads = malloc(sizeof(thread_t*) * threads);
+ while (threads)
+ {
+ this->threads[threads - 1] = thread_create((thread_main_t)dispatch,
+ this);
+ if (this->threads[threads - 1])
+ {
+ threads--;
+ }
+ }
+}
+
+METHOD(fast_dispatcher_t, waitsignal, void,
+ private_fast_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);
+}
+
+METHOD(fast_dispatcher_t, destroy, void,
+ private_fast_dispatcher_t *this)
+{
+ char *sid;
+ session_entry_t *entry;
+ enumerator_t *enumerator;
+
+ FCGX_ShutdownPending();
+ while (this->thread_count--)
+ {
+ thread_t *thread = this->threads[this->thread_count];
+ thread->cancel(thread);
+ thread->join(thread);
+ }
+ enumerator = this->sessions->create_enumerator(this->sessions);
+ while (enumerator->enumerate(enumerator, &sid, &entry))
+ {
+ session_entry_destroy(entry);
+ }
+ enumerator->destroy(enumerator);
+ this->sessions->destroy(this->sessions);
+ this->controllers->destroy_function(this->controllers, free);
+ this->filters->destroy_function(this->filters, free);
+ this->mutex->destroy(this->mutex);
+ free(this->threads);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+fast_dispatcher_t *fast_dispatcher_create(char *socket, bool debug, int timeout,
+ fast_context_constructor_t constructor, void *param)
+{
+ private_fast_dispatcher_t *this;
+
+ INIT(this,
+ .public = {
+ .add_controller = _add_controller,
+ .add_filter = _add_filter,
+ .run = _run,
+ .waitsignal = _waitsignal,
+ .destroy = _destroy,
+ },
+ .sessions = hashtable_create((void*)session_hash,
+ (void*)session_equals, 4096),
+ .controllers = linked_list_create(),
+ .filters = linked_list_create(),
+ .context_constructor = constructor,
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .param = param,
+ .timeout = timeout,
+ .last_cleanup = time_monotonic(NULL),
+ .debug = debug,
+ );
+
+ FCGX_Init();
+
+ if (socket)
+ {
+ unlink(socket);
+ this->fd = FCGX_OpenSocket(socket, 10);
+ }
+ return &this->public;
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup libfast libfast
+ * @{
+ * FastCGI Application Server w/ templates.
+ *
+ * Libfast is a framework to write web applications in an MVC fashion. It uses
+ * the ClearSilver template engine and communicates through FastCGI with
+ * the webserver. It is multithreaded and really fast.
+ *
+ * The application has a global context and a session context. The global
+ * context is accessed from all sessions simultaneously and therefore
+ * needs to be threadsave. Often a database wrapper is the global context.
+ * The session context is instanciated per session. Sessions are managed
+ * automatically through session cookies. The session context is kept alive
+ * until the session times out. It must implement the context_t interface and
+ * a #fast_context_constructor_t is needed to create instances. To each session,
+ * a set of controllers gets instanciated. The controller instances are per
+ * session, so you can hold private data for each user.
+ * Controllers need to implement the controller_t interface and need a
+ * #fast_controller_constructor_t function to create instances.
+ *
+ * A small example shows how to set up libfast:
+ * @code
+ fast_fast_dispatcher_t *dispatcher;
+ your_global_context_implementation_t *global;
+
+ global = initialize_your_global_context();
+
+ dispatcher = fast_dispatcher_create(NULL, FALSE, 180,
+ (context_constructor_t)your_session_context_create, global);
+ dispatcher->add_controller(dispatcher, your_controller1_create, param1);
+ dispatcher->add_controller(dispatcher, your_controller2_create, param2);
+
+ dispatcher->run(dispatcher, 20);
+
+ dispatcher->waitsignal(dispatcher);
+
+ dispatcher->destroy(dispatcher);
+ global->destroy();
+ @endcode
+ * @}
+ *
+ * @defgroup fast_dispatcher fast_dispatcher
+ * @{ @ingroup libfast
+ */
+
+#ifndef FAST_DISPATCHER_H_
+#define FAST_DISPATCHER_H_
+
+#include "fast_controller.h"
+#include "fast_filter.h"
+
+typedef struct fast_dispatcher_t fast_dispatcher_t;
+
+/**
+ * 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 fast_dispatcher_t {
+
+ /**
+ * Register a controller to the dispatcher.
+ *
+ * The first controller added serves as default controller. Client's
+ * get redirected to it if no other controller matches.
+ *
+ * @param constructor constructor function to the conntroller
+ * @param param param to pass to constructor
+ */
+ void (*add_controller)(fast_dispatcher_t *this,
+ fast_controller_constructor_t constructor,
+ void *param);
+
+ /**
+ * Add a filter to the dispatcher.
+ *
+ * @param constructor constructor to create filter in session
+ * @param param param to pass to constructor
+ */
+ void (*add_filter)(fast_dispatcher_t *this,
+ fast_filter_constructor_t constructor, void *param);
+
+ /**
+ * Start with dispatching.
+ *
+ * Instanciate a constant thread pool and start dispatching requests.
+ *
+ * @param threads number of dispatching threads
+ */
+ void (*run)(fast_dispatcher_t *this, int threads);
+
+ /**
+ * Wait for a relevant signal action.
+ */
+ void (*waitsignal)(fast_dispatcher_t *this);
+
+ /**
+ * Destroy the fast_dispatcher_t.
+ */
+ void (*destroy) (fast_dispatcher_t *this);
+};
+
+/**
+ * Create a dispatcher.
+ *
+ * The context constructor is invoked to create a session context for
+ * each session.
+ *
+ * @param socket FastCGI socket path, NULL for dynamic
+ * @param debug no stripping, no compression, timing information
+ * @param timeout session timeout
+ * @param constructor construction function for session context
+ * @param param parameter to supply to context constructor
+ */
+fast_dispatcher_t *fast_dispatcher_create(char *socket, bool debug, int timeout,
+ fast_context_constructor_t constructor, void *param);
+
+#endif /** FAST_DISPATCHER_H_ @}*/
--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * @defgroup fast_filter fast_filter
+ * @{ @ingroup libfast
+ */
+
+#ifndef FAST_FILTER_H_
+#define FAST_FILTER_H_
+
+#include "fast_request.h"
+#include "fast_context.h"
+#include "fast_controller.h"
+
+typedef struct fast_filter_t fast_filter_t;
+
+/**
+ * Constructor function for a filter
+ *
+ * @param context session specific context
+ * @param param user supplied param
+ */
+typedef fast_filter_t *(*fast_filter_constructor_t)(fast_context_t* context,
+ void *param);
+
+/**
+ * Filter interface, to be implemented by users filters.
+ */
+struct fast_filter_t {
+
+ /**
+ * Called before the controller handles the request.
+ *
+ * @param request HTTP request
+ * @param p1 first parameter
+ * @param p2 second parameter
+ * @param p3 third parameter
+ * @param p4 forth parameter
+ * @param p5 fifth parameter
+ * @return TRUE to continue request handling
+ */
+ bool (*run)(fast_filter_t *this, fast_request_t *request,
+ char *p0, char *p1, char *p2, char *p3, char *p4, char *p5);
+
+ /**
+ * Destroy the filter instance.
+ */
+ void (*destroy) (fast_filter_t *this);
+};
+
+#endif /* FAST_FILTER_H_ @} */
--- /dev/null
+/*
+ * 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 "fast_request.h"
+
+#include <library.h>
+#include <utils/debug.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <ClearSilver/ClearSilver.h>
+
+#include <threading/thread.h>
+#include <threading/thread_value.h>
+
+typedef struct private_fast_request_t private_fast_request_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_fast_request_t {
+
+ /**
+ * public functions
+ */
+ fast_request_t public;
+
+ /**
+ * FastCGI request object
+ */
+ FCGX_Request req;
+
+ /**
+ * length of the req.envp array
+ */
+ int req_env_len;
+
+ /**
+ * ClearSilver CGI Kit context
+ */
+ CGI *cgi;
+
+ /**
+ * ClearSilver HDF dataset for this request
+ */
+ HDF *hdf;
+
+ /**
+ * close the session?
+ */
+ bool closed;
+
+ /**
+ * reference count
+ */
+ refcount_t ref;
+};
+
+/**
+ * ClearSilver cgiwrap is not threadsave, so we use a private
+ * context for each thread.
+ */
+static thread_value_t *thread_this;
+
+/**
+ * control variable for pthread_once
+ */
+pthread_once_t once = PTHREAD_ONCE_INIT;
+
+/**
+ * fcgiwrap read callback
+ */
+static int read_cb(void *null, char *buf, int size)
+{
+ private_fast_request_t *this;
+
+ this = (private_fast_request_t*)thread_this->get(thread_this);
+
+ return FCGX_GetStr(buf, size, this->req.in);
+}
+
+/**
+ * fcgiwrap writef callback
+ */
+static int writef_cb(void *null, const char *format, va_list args)
+{
+ private_fast_request_t *this;
+
+ this = (private_fast_request_t*)thread_this->get(thread_this);
+
+ FCGX_VFPrintF(this->req.out, format, args);
+ return 0;
+}
+/**
+ * fcgiwrap write callback
+ */
+static int write_cb(void *null, const char *buf, int size)
+{
+ private_fast_request_t *this;
+
+ this = (private_fast_request_t*)thread_this->get(thread_this);
+
+ return FCGX_PutStr(buf, size, this->req.out);
+}
+
+/**
+ * fcgiwrap getenv callback
+ */
+static char *getenv_cb(void *null, const char *key)
+{
+ char *value;
+ private_fast_request_t *this;
+
+ this = (private_fast_request_t*)thread_this->get(thread_this);
+
+ value = FCGX_GetParam(key, this->req.envp);
+ return strdupnull(value);
+}
+
+/**
+ * fcgiwrap getenv callback
+ */
+static int putenv_cb(void *null, const char *key, const char *value)
+{
+ /* not supported */
+ return 1;
+}
+
+/**
+ * fcgiwrap iterenv callback
+ */
+static int iterenv_cb(void *null, int num, char **key, char **value)
+{
+ private_fast_request_t *this;
+
+ *key = NULL;
+ *value = NULL;
+ this = (private_fast_request_t*)thread_this->get(thread_this);
+
+ if (num < this->req_env_len)
+ {
+ char *eq;
+
+ eq = strchr(this->req.envp[num], '=');
+ if (eq)
+ {
+ *key = strndup(this->req.envp[num], eq - this->req.envp[num]);
+ *value = strdup(eq + 1);
+ }
+ if (*key == NULL || *value == NULL)
+ {
+ free(*key);
+ free(*value);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+METHOD(fast_request_t, get_cookie, char*,
+ private_fast_request_t *this, char *name)
+{
+ return hdf_get_valuef(this->hdf, "Cookie.%s", name);
+}
+
+METHOD(fast_request_t, get_path, char*,
+ private_fast_request_t *this)
+{
+ char *path = FCGX_GetParam("PATH_INFO", this->req.envp);
+ return path ? path : "";
+}
+
+METHOD(fast_request_t, get_host, char*,
+ private_fast_request_t *this)
+{
+ char *addr = FCGX_GetParam("REMOTE_ADDR", this->req.envp);
+ return addr ? addr : "";
+}
+
+METHOD(fast_request_t, get_user_agent, char*,
+ private_fast_request_t *this)
+{
+ char *agent = FCGX_GetParam("HTTP_USER_AGENT", this->req.envp);
+ return agent ? agent : "";
+}
+
+METHOD(fast_request_t, get_query_data, char*,
+ private_fast_request_t *this, char *name)
+{
+ return hdf_get_valuef(this->hdf, "Query.%s", name);
+}
+
+METHOD(fast_request_t, get_env_var, char*,
+ private_fast_request_t *this, char *name)
+{
+ return FCGX_GetParam(name, this->req.envp);
+}
+
+METHOD(fast_request_t, read_data, int,
+ private_fast_request_t *this, char *buf, int len)
+{
+ return FCGX_GetStr(buf, len, this->req.in);
+}
+
+METHOD(fast_request_t, get_base, char*,
+ private_fast_request_t *this)
+{
+ return FCGX_GetParam("SCRIPT_NAME", this->req.envp);
+}
+
+METHOD(fast_request_t, add_cookie, void,
+ private_fast_request_t *this, char *name, char *value)
+{
+ thread_this->set(thread_this, this);
+ cgi_cookie_set(this->cgi, name, value, NULL, NULL, NULL, 0, 0);
+}
+
+METHOD(fast_request_t, redirect, void,
+ private_fast_request_t *this, char *fmt, ...)
+{
+ va_list args;
+
+ FCGX_FPrintF(this->req.out, "Status: 303 See Other\n");
+ FCGX_FPrintF(this->req.out, "Location: %s%s", get_base(this),
+ *fmt == '/' ? "" : "/");
+ va_start(args, fmt);
+ FCGX_VFPrintF(this->req.out, fmt, args);
+ va_end(args);
+ FCGX_FPrintF(this->req.out, "\n\n");
+}
+
+METHOD(fast_request_t, get_referer, char*,
+ private_fast_request_t *this)
+{
+ return FCGX_GetParam("HTTP_REFERER", this->req.envp);
+}
+
+METHOD(fast_request_t, to_referer, void,
+ private_fast_request_t *this)
+{
+ char *referer;
+
+ referer = get_referer(this);
+ if (referer)
+ {
+ FCGX_FPrintF(this->req.out, "Status: 303 See Other\n");
+ FCGX_FPrintF(this->req.out, "Location: %s\n\n", referer);
+ }
+ else
+ {
+ redirect(this, "/");
+ }
+}
+
+METHOD(fast_request_t, session_closed, bool,
+ private_fast_request_t *this)
+{
+ return this->closed;
+}
+
+METHOD(fast_request_t, close_session, void,
+ private_fast_request_t *this)
+{
+ this->closed = TRUE;
+}
+
+METHOD(fast_request_t, serve, void,
+ private_fast_request_t *this, char *headers, chunk_t chunk)
+{
+ FCGX_FPrintF(this->req.out, "%s\n\n", headers);
+
+ FCGX_PutStr(chunk.ptr, chunk.len, this->req.out);
+}
+
+METHOD(fast_request_t, sendfile, bool,
+ private_fast_request_t *this, char *path, char *mime)
+{
+ struct stat sb;
+ chunk_t data;
+ void *addr;
+ int fd, written;
+ char buf[24];
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ {
+ return FALSE;
+ }
+ if (fstat(fd, &sb) == -1)
+ {
+ close(fd);
+ return FALSE;
+ }
+ addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (addr == MAP_FAILED)
+ {
+ close(fd);
+ return FALSE;
+ }
+
+ /* FCGX does not like large integers, print to a buffer using libc */
+ snprintf(buf, sizeof(buf), "%lld", (int64_t)sb.st_size);
+ FCGX_FPrintF(this->req.out, "Content-Length: %s\n", buf);
+ if (mime)
+ {
+ FCGX_FPrintF(this->req.out, "Content-Type: %s\n", mime);
+ }
+ FCGX_FPrintF(this->req.out, "\n");
+
+ data = chunk_create(addr, sb.st_size);
+
+ while (data.len)
+ {
+ written = FCGX_PutStr(data.ptr, data.len, this->req.out);
+ if (written == -1)
+ {
+ munmap(addr, sb.st_size);
+ close(fd);
+ return FALSE;
+ }
+ data = chunk_skip(data, written);
+ }
+
+ munmap(addr, sb.st_size);
+ close(fd);
+ return TRUE;
+}
+
+METHOD(fast_request_t, render, void,
+ private_fast_request_t *this, char *template)
+{
+ NEOERR* err;
+
+ thread_this->set(thread_this, this);
+ err = cgi_display(this->cgi, template);
+ if (err)
+ {
+ cgi_neo_error(this->cgi, err);
+ nerr_log_error(err);
+ }
+}
+
+METHOD(fast_request_t, streamf, int,
+ private_fast_request_t *this, char *format, ...)
+{
+ va_list args;
+ int written;
+
+ va_start(args, format);
+ written = FCGX_VFPrintF(this->req.out, format, args);
+ va_end(args);
+ if (written >= 0 &&
+ FCGX_FFlush(this->req.out) == -1)
+ {
+ return -1;
+ }
+ return written;
+}
+
+METHOD(fast_request_t, set, void,
+ private_fast_request_t *this, char *key, char *value)
+{
+ hdf_set_value(this->hdf, key, value);
+}
+
+METHOD(fast_request_t, setf, void,
+ private_fast_request_t *this, char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ hdf_set_valuevf(this->hdf, format, args);
+ va_end(args);
+}
+
+METHOD(fast_request_t, get_ref, fast_request_t*,
+ private_fast_request_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
+METHOD(fast_request_t, destroy, void,
+ private_fast_request_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ thread_this->set(thread_this, this);
+ cgi_destroy(&this->cgi);
+ FCGX_Finish_r(&this->req);
+ free(this);
+ }
+}
+
+/**
+ * This initialization method is guaranteed to run only once
+ * for all threads.
+ */
+static void init(void)
+{
+ cgiwrap_init_emu(NULL, read_cb, writef_cb, write_cb,
+ getenv_cb, putenv_cb, iterenv_cb);
+ thread_this = thread_value_create(NULL);
+}
+
+/*
+ * see header file
+ */
+fast_request_t *fast_request_create(int fd, bool debug)
+{
+ NEOERR* err;
+ private_fast_request_t *this;
+ bool failed = FALSE;
+
+ INIT(this,
+ .public = {
+ .get_path = _get_path,
+ .get_base = _get_base,
+ .get_host = _get_host,
+ .get_user_agent = _get_user_agent,
+ .add_cookie = _add_cookie,
+ .get_cookie = _get_cookie,
+ .get_query_data = _get_query_data,
+ .get_env_var = _get_env_var,
+ .read_data = _read_data,
+ .session_closed = _session_closed,
+ .close_session = _close_session,
+ .redirect = _redirect,
+ .get_referer = _get_referer,
+ .to_referer = _to_referer,
+ .render = _render,
+ .streamf = _streamf,
+ .serve = _serve,
+ .sendfile = _sendfile,
+ .set = _set,
+ .setf = _setf,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .ref = 1,
+ );
+
+ thread_cleanup_push(free, this);
+ if (FCGX_InitRequest(&this->req, fd, 0) != 0 ||
+ FCGX_Accept_r(&this->req) != 0)
+ {
+ failed = TRUE;
+ }
+ thread_cleanup_pop(failed);
+ if (failed)
+ {
+ return NULL;
+ }
+
+ pthread_once(&once, init);
+ thread_this->set(thread_this, this);
+
+ while (this->req.envp[this->req_env_len] != NULL)
+ {
+ this->req_env_len++;
+ }
+
+ err = hdf_init(&this->hdf);
+ if (!err)
+ {
+ hdf_set_value(this->hdf, "base", get_base(this));
+ hdf_set_value(this->hdf, "Config.NoCache", "true");
+ if (!debug)
+ {
+ hdf_set_value(this->hdf, "Config.TimeFooter", "0");
+ hdf_set_value(this->hdf, "Config.CompressionEnabled", "1");
+ hdf_set_value(this->hdf, "Config.WhiteSpaceStrip", "2");
+ }
+
+ err = cgi_init(&this->cgi, this->hdf);
+ if (!err)
+ {
+ err = cgi_parse(this->cgi);
+ if (!err)
+ {
+ return &this->public;
+ }
+ cgi_destroy(&this->cgi);
+ }
+ }
+ nerr_log_error(err);
+ FCGX_Finish_r(&this->req);
+ free(this);
+ return NULL;
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup fast_request fast_request
+ * @{ @ingroup libfast
+ */
+
+#ifndef FAST_REQUEST_H_
+#define FAST_REQUEST_H_
+
+#include <fcgiapp.h>
+#include <library.h>
+
+typedef struct fast_request_t fast_request_t;
+
+/**
+ * A HTTP request, encapsulates FCGX_Request.
+ *
+ * The response is also handled through the request object.
+ */
+struct fast_request_t {
+
+ /**
+ * Add a cookie to the reply (Set-Cookie header).
+ *
+ * @param name name of the cookie to set
+ * @param value value of the cookie
+ */
+ void (*add_cookie)(fast_request_t *this, char *name, char *value);
+
+ /**
+ * 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)(fast_request_t *this, char *name);
+
+ /**
+ * Get the request path relative to the application.
+ *
+ * @return path
+ */
+ char* (*get_path)(fast_request_t *this);
+
+ /**
+ * Get the base path of the application.
+ *
+ * @return base path
+ */
+ char* (*get_base)(fast_request_t *this);
+
+ /**
+ * Get the remote host address of this request.
+ *
+ * @return host address as string
+ */
+ char* (*get_host)(fast_request_t *this);
+
+ /**
+ * Get the user agent string.
+ *
+ * @return user agent string
+ */
+ char* (*get_user_agent)(fast_request_t *this);
+
+ /**
+ * Get a post/get variable included in the request.
+ *
+ * @param name name of the POST/GET variable
+ * @return value, NULL if not found
+ */
+ char* (*get_query_data)(fast_request_t *this, char *name);
+
+ /**
+ * Get an arbitrary environment variable.
+ *
+ * @param name name of the environment variable
+ * @return value, NULL if not found
+ */
+ char* (*get_env_var)(fast_request_t *this, char *name);
+
+ /**
+ * Read raw POST/PUT data from HTTP request.
+ *
+ * @param buf buffer to read data into
+ * @param len size of the supplied buffer
+ * @return number of bytes read, < 0 on error
+ */
+ int (*read_data)(fast_request_t *this, char *buf, int len);
+
+ /**
+ * Close the session and it's context after handling.
+ */
+ void (*close_session)(fast_request_t *this);
+
+ /**
+ * Has the session been closed by close_session()?
+ *
+ * @return TRUE if session has been closed
+ */
+ bool (*session_closed)(fast_request_t *this);
+
+ /**
+ * Redirect the client to another location.
+ *
+ * @param fmt location format string
+ * @param ... variable argument for fmt
+ */
+ void (*redirect)(fast_request_t *this, char *fmt, ...);
+
+ /**
+ * Get the HTTP referer.
+ *
+ * @return HTTP referer
+ */
+ char* (*get_referer)(fast_request_t *this);
+
+ /**
+ * Redirect back to the referer.
+ */
+ void (*to_referer)(fast_request_t *this);
+
+ /**
+ * Set a template value.
+ *
+ * @param key key to set
+ * @param value value to set key to
+ */
+ void (*set)(fast_request_t *this, char *key, char *value);
+
+ /**
+ * 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)(fast_request_t *this, char *format, ...);
+
+ /**
+ * Render a template.
+ *
+ * The render() function additionally sets a HDF variable "base"
+ * which points to the root of the web application and allows to point to
+ * other targets without to worry about path location.
+ *
+ * @param template clearsilver template file location
+ */
+ void (*render)(fast_request_t *this, char *template);
+
+ /**
+ * Stream a format string to the client.
+ *
+ * Stream is not closed and may be called multiple times to allow
+ * server-push functionality.
+ *
+ * @param format printf like format string
+ * @param ... argmuent list to format string
+ * @return number of streamed bytes, < 0 if stream closed
+ */
+ int (*streamf)(fast_request_t *this, char *format, ...);
+
+ /**
+ * Serve a request with headers and a body.
+ *
+ * @param headers HTTP headers, \n separated
+ * @param chunk body to write to output
+ */
+ void (*serve)(fast_request_t *this, char *headers, chunk_t chunk);
+
+ /**
+ * Send a file from the file system.
+ *
+ * @param path path to file to serve
+ * @param mime mime type of file to send, or NULL
+ * @return TRUE if file served successfully
+ */
+ bool (*sendfile)(fast_request_t *this, char *path, char *mime);
+
+ /**
+ * Increase the reference count to the stream.
+ *
+ * @return this with increased refcount
+ */
+ fast_request_t* (*get_ref)(fast_request_t *this);
+
+ /**
+ * Destroy the fast_request_t.
+ */
+ void (*destroy) (fast_request_t *this);
+};
+
+/**
+ * Create a request from the fastcgi struct.
+ *
+ * @param fd file descripter opened with FCGX_OpenSocket
+ * @param debug no stripping, no compression, timing information
+ */
+fast_request_t *fast_request_create(int fd, bool debug);
+
+#endif /** REQUEST_H_ @}*/
--- /dev/null
+/*
+ * 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 "fast_session.h"
+
+#include <string.h>
+#include <fcgiapp.h>
+#include <stdio.h>
+
+#include <collections/linked_list.h>
+
+#define COOKIE_LEN 16
+
+typedef struct private_fast_session_t private_fast_session_t;
+
+/**
+ * private data of the task manager
+ */
+struct private_fast_session_t {
+
+ /**
+ * public functions
+ */
+ fast_session_t public;
+
+ /**
+ * session ID
+ */
+ char sid[COOKIE_LEN * 2 + 1];
+
+ /**
+ * have we sent the session cookie?
+ */
+ bool cookie_sent;
+
+ /**
+ * list of controller instances controller_t
+ */
+ linked_list_t *controllers;
+
+ /**
+ * list of filter instances filter_t
+ */
+ linked_list_t *filters;
+
+ /**
+ * user defined session context
+ */
+ fast_context_t *context;
+};
+
+METHOD(fast_session_t, add_controller, void,
+ private_fast_session_t *this, fast_controller_t *controller)
+{
+ this->controllers->insert_last(this->controllers, controller);
+}
+
+METHOD(fast_session_t, add_filter, void,
+ private_fast_session_t *this, fast_filter_t *filter)
+{
+ this->filters->insert_last(this->filters, filter);
+}
+
+/**
+ * Create a session ID and a cookie
+ */
+static bool create_sid(private_fast_session_t *this)
+{
+ char buf[COOKIE_LEN];
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ return FALSE;
+ }
+ if (!rng->get_bytes(rng, sizeof(buf), buf))
+ {
+ rng->destroy(rng);
+ return FALSE;
+ }
+ rng->destroy(rng);
+ chunk_to_hex(chunk_create(buf, sizeof(buf)), this->sid, FALSE);
+ return TRUE;
+}
+
+/**
+ * run all registered filters
+ */
+static bool run_filter(private_fast_session_t *this, fast_request_t *request,
+ char *p0, char *p1, char *p2, char *p3, char *p4, char *p5)
+{
+ enumerator_t *enumerator;
+ fast_filter_t *filter;
+
+ enumerator = this->filters->create_enumerator(this->filters);
+ while (enumerator->enumerate(enumerator, &filter))
+ {
+ if (!filter->run(filter, request, p0, p1, p2, p3, p4, p5))
+ {
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return TRUE;
+}
+
+METHOD(fast_session_t, process, void,
+ private_fast_session_t *this, fast_request_t *request)
+{
+ char *pos, *start, *param[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
+ enumerator_t *enumerator;
+ bool handled = FALSE;
+ fast_controller_t *current;
+ int i = 0;
+
+ if (!this->cookie_sent)
+ {
+ request->add_cookie(request, "SID", this->sid);
+ this->cookie_sent = TRUE;
+ }
+
+ start = request->get_path(request);
+ if (start)
+ {
+ if (*start == '/')
+ {
+ start++;
+ }
+ while ((pos = strchr(start, '/')) != NULL && i < 5)
+ {
+ param[i++] = strndupa(start, pos - start);
+ start = pos + 1;
+ }
+ param[i] = strdupa(start);
+
+ if (run_filter(this, request, param[0], param[1], param[2], param[3],
+ param[4], param[5]))
+ {
+ enumerator = this->controllers->create_enumerator(this->controllers);
+ while (enumerator->enumerate(enumerator, ¤t))
+ {
+ if (streq(current->get_name(current), param[0]))
+ {
+ current->handle(current, request, param[1], param[2],
+ param[3], param[4], param[5]);
+ handled = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ handled = TRUE;
+ }
+ }
+ if (!handled)
+ {
+ if (this->controllers->get_first(this->controllers,
+ (void**)¤t) == SUCCESS)
+ {
+ request->streamf(request,
+ "Status: 301 Moved permanently\nLocation: %s/%s\n\n",
+ request->get_base(request), current->get_name(current));
+ }
+ }
+}
+
+METHOD(fast_session_t, get_sid, char*,
+ private_fast_session_t *this)
+{
+ return this->sid;
+}
+
+METHOD(fast_session_t, destroy, void,
+ private_fast_session_t *this)
+{
+ this->controllers->destroy_offset(this->controllers,
+ offsetof(fast_controller_t, destroy));
+ this->filters->destroy_offset(this->filters,
+ offsetof(fast_filter_t, destroy));
+ DESTROY_IF(this->context);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+fast_session_t *fast_session_create(fast_context_t *context)
+{
+ private_fast_session_t *this;
+
+ INIT(this,
+ .public = {
+ .add_controller = _add_controller,
+ .add_filter = _add_filter,
+ .process = _process,
+ .get_sid = _get_sid,
+ .destroy = _destroy,
+ },
+ .controllers = linked_list_create(),
+ .filters = linked_list_create(),
+ .context = context,
+ );
+ if (!create_sid(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup fast_session fast_session
+ * @{ @ingroup libfast
+ */
+
+#ifndef FAST_SESSION_H_
+#define FAST_SESSION_H_
+
+#include "fast_request.h"
+#include "fast_controller.h"
+#include "fast_filter.h"
+
+typedef struct fast_session_t fast_session_t;
+
+/**
+ * Session handling class, instanciated for each user session.
+ */
+struct fast_session_t {
+
+ /**
+ * Get the session ID of the session.
+ *
+ * @return session ID
+ */
+ char* (*get_sid)(fast_session_t *this);
+
+ /**
+ * Add a controller instance to the session.
+ *
+ * @param controller controller to add
+ */
+ void (*add_controller)(fast_session_t *this, fast_controller_t *controller);
+
+ /**
+ * Add a filter instance to the session.
+ *
+ * @param filter filter to add
+ */
+ void (*add_filter)(fast_session_t *this, fast_filter_t *filter);
+
+ /**
+ * Process a request in this session.
+ *
+ * @param request request to process
+ */
+ void (*process)(fast_session_t *this, fast_request_t *request);
+
+ /**
+ * Destroy the fast_session_t.
+ */
+ void (*destroy) (fast_session_t *this);
+};
+
+/**
+ * Create a session new session.
+ *
+ * @param context user defined session context instance
+ * @return client session, NULL on error
+ */
+fast_session_t *fast_session_create(fast_context_t *context);
+
+#endif /** SESSION_H_ @}*/
--- /dev/null
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 "fast_smtp.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <utils/debug.h>
+
+typedef struct private_fast_smtp_t private_fast_smtp_t;
+
+/**
+ * Private data of an fast_smtp_t object.
+ */
+struct private_fast_smtp_t {
+
+ /**
+ * Public fast_smtp_t interface.
+ */
+ fast_smtp_t public;
+
+ /**
+ * file stream to SMTP server
+ */
+ FILE *f;
+};
+
+/**
+ * Read the response code from an SMTP server
+ */
+static int read_response(private_fast_smtp_t *this)
+{
+ char buf[256], *end;
+ int res = 0;
+
+ while (TRUE)
+ {
+ if (!fgets(buf, sizeof(buf), this->f))
+ {
+ return 0;
+ }
+ res = strtol(buf, &end, 10);
+ switch (*end)
+ {
+ case '-':
+ continue;
+ case ' ':
+ case '\0':
+ case '\n':
+ break;
+ default:
+ return 0;
+ }
+ break;
+ }
+ return res;
+}
+
+/**
+ * write a SMTP command to the server, read response code
+ */
+static int write_cmd(private_fast_smtp_t *this, char *fmt, ...)
+{
+ char buf[256];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (fprintf(this->f, "%s\n", buf) < 1)
+ {
+ DBG1(DBG_LIB, "sending SMTP command failed");
+ return 0;
+ }
+ return read_response(this);
+}
+
+METHOD(fast_smtp_t, send_mail, bool,
+ private_fast_smtp_t *this, char *from, char *to, char *subject, char *fmt, ...)
+{
+ va_list args;
+
+ if (write_cmd(this, "MAIL FROM:<%s>", from) != 250)
+ {
+ DBG1(DBG_LIB, "SMTP MAIL FROM failed");
+ return FALSE;
+ }
+ if (write_cmd(this, "RCPT TO:<%s>", to) != 250)
+ {
+ DBG1(DBG_LIB, "SMTP RCPT TO failed");
+ return FALSE;
+ }
+ if (write_cmd(this, "DATA") != 354)
+ {
+ DBG1(DBG_LIB, "SMTP DATA failed");
+ return FALSE;
+ }
+
+ fprintf(this->f, "From: %s\n", from);
+ fprintf(this->f, "To: %s\n", to);
+ fprintf(this->f, "Subject: %s\n", subject);
+ fprintf(this->f, "\n");
+ va_start(args, fmt);
+ vfprintf(this->f, fmt, args);
+ va_end(args);
+ fprintf(this->f, "\n.\n");
+ return read_response(this) == 250;
+}
+
+
+METHOD(fast_smtp_t, destroy, void,
+ private_fast_smtp_t *this)
+{
+ write_cmd(this, "QUIT");
+ fclose(this->f);
+ free(this);
+}
+
+/**
+ * See header
+ */
+fast_smtp_t *fast_smtp_create()
+{
+ private_fast_smtp_t *this;
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_port = htons(25),
+ .sin_addr = {
+ .s_addr = htonl(INADDR_LOOPBACK),
+ },
+ };
+ int s;
+
+ INIT(this,
+ .public = {
+ .send_mail = _send_mail,
+ .destroy = _destroy,
+ },
+ );
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ {
+ DBG1(DBG_LIB, "opening SMTP socket failed: %s", strerror(errno));
+ free(this);
+ return NULL;
+ }
+ if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0)
+ {
+ DBG1(DBG_LIB, "connecting to SMTP server failed: %s", strerror(errno));
+ close(s);
+ free(this);
+ return NULL;
+ }
+ this->f = fdopen(s, "a+");
+ if (!this->f)
+ {
+ DBG1(DBG_LIB, "opening stream to SMTP server failed: %s",
+ strerror(errno));
+ close(s);
+ free(this);
+ return NULL;
+ }
+ if (read_response(this) != 220 ||
+ write_cmd(this, "EHLO localhost") != 250)
+ {
+ DBG1(DBG_LIB, "SMTP EHLO failed");
+ fclose(this->f);
+ free(this);
+ return NULL;
+ }
+ return &this->public;
+}
--- /dev/null
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup fast_smtp fast_smtp
+ * @{ @ingroup libfast
+ */
+
+#ifndef FAST_SMTP_H_
+#define FAST_SMTP_H_
+
+typedef struct fast_smtp_t fast_smtp_t;
+
+#include <library.h>
+
+/**
+ * Ultra-minimalistic SMTP client. Works at most with Exim on localhost.
+ */
+struct fast_smtp_t {
+
+ /**
+ * Send an e-mail message.
+ *
+ * @param from sender address
+ * @param to recipient address
+ * @param subject mail subject
+ * @param fmt mail body format string
+ * @param ... arguments for body format string
+ */
+ bool (*send_mail)(fast_smtp_t *this, char *from, char *to,
+ char *subject, char *fmt, ...);
+
+ /**
+ * Destroy a fast_smtp_t.
+ */
+ void (*destroy)(fast_smtp_t *this);
+};
+
+/**
+ * Create a smtp instance.
+ */
+fast_smtp_t *fast_smtp_create();
+
+#endif /** FAST_SMTP_H_ @}*/
+++ /dev/null
-/*
- * Copyright (C) 2008 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.
- */
-
-/*
- * @defgroup filter filter
- * @{ @ingroup libfast
- */
-
-#ifndef FILTER_H_
-#define FILTER_H_
-
-#include "request.h"
-#include "context.h"
-#include "controller.h"
-
-typedef struct filter_t filter_t;
-
-/**
- * Constructor function for a filter
- *
- * @param context session specific context
- * @param param user supplied param
- */
-typedef filter_t *(*filter_constructor_t)(context_t* context, void *param);
-
-/**
- * Filter interface, to be implemented by users filters.
- */
-struct filter_t {
-
- /**
- * Called before the controller handles the request.
- *
- * @param request HTTP request
- * @param p1 first parameter
- * @param p2 second parameter
- * @param p3 third parameter
- * @param p4 forth parameter
- * @param p5 fifth parameter
- * @return TRUE to continue request handling
- */
- bool (*run)(filter_t *this, request_t *request,
- char *p0, char *p1, char *p2, char *p3, char *p4, char *p5);
-
- /**
- * Destroy the filter instance.
- */
- void (*destroy) (filter_t *this);
-};
-
-#endif /* FILTER_H_ @} */
+++ /dev/null
-/*
- * 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 <library.h>
-#include <utils/debug.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <ClearSilver/ClearSilver.h>
-
-#include <threading/thread.h>
-#include <threading/thread_value.h>
-
-typedef struct private_request_t private_request_t;
-
-/**
- * private data of the task manager
- */
-struct private_request_t {
-
- /**
- * public functions
- */
- request_t public;
-
- /**
- * FastCGI request object
- */
- FCGX_Request req;
-
- /**
- * length of the req.envp array
- */
- int req_env_len;
-
- /**
- * ClearSilver CGI Kit context
- */
- CGI *cgi;
-
- /**
- * ClearSilver HDF dataset for this request
- */
- HDF *hdf;
-
- /**
- * close the session?
- */
- bool closed;
-
- /**
- * reference count
- */
- refcount_t ref;
-};
-
-/**
- * ClearSilver cgiwrap is not threadsave, so we use a private
- * context for each thread.
- */
-static thread_value_t *thread_this;
-
-/**
- * control variable for pthread_once
- */
-pthread_once_t once = PTHREAD_ONCE_INIT;
-
-/**
- * fcgiwrap read callback
- */
-static int read_cb(void *null, char *buf, int size)
-{
- private_request_t *this = (private_request_t*)thread_this->get(thread_this);
-
- return FCGX_GetStr(buf, size, this->req.in);
-}
-
-/**
- * fcgiwrap writef callback
- */
-static int writef_cb(void *null, const char *format, va_list args)
-{
- private_request_t *this = (private_request_t*)thread_this->get(thread_this);
-
- FCGX_VFPrintF(this->req.out, format, args);
- return 0;
-}
-/**
- * fcgiwrap write callback
- */
-static int write_cb(void *null, const char *buf, int size)
-{
- private_request_t *this = (private_request_t*)thread_this->get(thread_this);
-
- return FCGX_PutStr(buf, size, this->req.out);
-}
-
-/**
- * fcgiwrap getenv callback
- */
-static char *getenv_cb(void *null, const char *key)
-{
- char *value;
- private_request_t *this = (private_request_t*)thread_this->get(thread_this);
-
- value = FCGX_GetParam(key, this->req.envp);
- return strdupnull(value);
-}
-
-/**
- * fcgiwrap getenv callback
- */
-static int putenv_cb(void *null, const char *key, const char *value)
-{
- /* not supported */
- return 1;
-}
-
-/**
- * fcgiwrap iterenv callback
- */
-static int iterenv_cb(void *null, int num, char **key, char **value)
-{
- *key = NULL;
- *value = NULL;
- private_request_t *this = (private_request_t*)thread_this->get(thread_this);
- if (num < this->req_env_len)
- {
- char *eq;
-
- eq = strchr(this->req.envp[num], '=');
- if (eq)
- {
- *key = strndup(this->req.envp[num], eq - this->req.envp[num]);
- *value = strdup(eq + 1);
- }
- if (*key == NULL || *value == NULL)
- {
- free(*key);
- free(*value);
- return 1;
- }
- }
- return 0;
-}
-
-METHOD(request_t, get_cookie, char*,
- private_request_t *this, char *name)
-{
- return hdf_get_valuef(this->hdf, "Cookie.%s", name);
-}
-
-METHOD(request_t, get_path, char*,
- private_request_t *this)
-{
- char * path = FCGX_GetParam("PATH_INFO", this->req.envp);
- return path ? path : "";
-}
-
-METHOD(request_t, get_host, char*,
- private_request_t *this)
-{
- char *addr = FCGX_GetParam("REMOTE_ADDR", this->req.envp);
- return addr ? addr : "";
-}
-
-METHOD(request_t, get_user_agent, char*,
- private_request_t *this)
-{
- char *agent = FCGX_GetParam("HTTP_USER_AGENT", this->req.envp);
- return agent ? agent : "";
-}
-
-METHOD(request_t, get_query_data, char*,
- private_request_t *this, char *name)
-{
- return hdf_get_valuef(this->hdf, "Query.%s", name);
-}
-
-METHOD(request_t, get_env_var, char*,
- private_request_t *this, char *name)
-{
- return FCGX_GetParam(name, this->req.envp);
-}
-
-METHOD(request_t, read_data, int,
- private_request_t *this, char *buf, int len)
-{
- return FCGX_GetStr(buf, len, this->req.in);
-}
-
-METHOD(request_t, get_base, char*,
- private_request_t *this)
-{
- return FCGX_GetParam("SCRIPT_NAME", this->req.envp);
-}
-
-METHOD(request_t, add_cookie, void,
- private_request_t *this, char *name, char *value)
-{
- thread_this->set(thread_this, this);
- cgi_cookie_set(this->cgi, name, value, NULL, NULL, NULL, 0, 0);
-}
-
-METHOD(request_t, redirect, void,
- private_request_t *this, char *fmt, ...)
-{
- va_list args;
-
- FCGX_FPrintF(this->req.out, "Status: 303 See Other\n");
- FCGX_FPrintF(this->req.out, "Location: %s%s", get_base(this),
- *fmt == '/' ? "" : "/");
- va_start(args, fmt);
- FCGX_VFPrintF(this->req.out, fmt, args);
- va_end(args);
- FCGX_FPrintF(this->req.out, "\n\n");
-}
-
-METHOD(request_t, get_referer, char*,
- private_request_t *this)
-{
- return FCGX_GetParam("HTTP_REFERER", this->req.envp);
-}
-
-METHOD(request_t, to_referer, void,
- private_request_t *this)
-{
- char *referer;
-
- referer = get_referer(this);
- if (referer)
- {
- FCGX_FPrintF(this->req.out, "Status: 303 See Other\n");
- FCGX_FPrintF(this->req.out, "Location: %s\n\n", referer);
- }
- else
- {
- redirect(this, "/");
- }
-}
-
-METHOD(request_t, session_closed, bool,
- private_request_t *this)
-{
- return this->closed;
-}
-
-METHOD(request_t, close_session, void,
- private_request_t *this)
-{
- this->closed = TRUE;
-}
-
-METHOD(request_t, serve, void,
- private_request_t *this, char *headers, chunk_t chunk)
-{
- FCGX_FPrintF(this->req.out, "%s\n\n", headers);
-
- FCGX_PutStr(chunk.ptr, chunk.len, this->req.out);
-}
-
-METHOD(request_t, sendfile, bool,
- private_request_t *this, char *path, char *mime)
-{
- struct stat sb;
- chunk_t data;
- void *addr;
- int fd, written;
- char buf[24];
-
- fd = open(path, O_RDONLY);
- if (fd == -1)
- {
- return FALSE;
- }
- if (fstat(fd, &sb) == -1)
- {
- close(fd);
- return FALSE;
- }
- addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (addr == MAP_FAILED)
- {
- close(fd);
- return FALSE;
- }
-
- /* FCGX does not like large integers, print to a buffer using libc */
- snprintf(buf, sizeof(buf), "%lld", (int64_t)sb.st_size);
- FCGX_FPrintF(this->req.out, "Content-Length: %s\n", buf);
- if (mime)
- {
- FCGX_FPrintF(this->req.out, "Content-Type: %s\n", mime);
- }
- FCGX_FPrintF(this->req.out, "\n");
-
- data = chunk_create(addr, sb.st_size);
-
- while (data.len)
- {
- written = FCGX_PutStr(data.ptr, data.len, this->req.out);
- if (written == -1)
- {
- munmap(addr, sb.st_size);
- close(fd);
- return FALSE;
- }
- data = chunk_skip(data, written);
- }
-
- munmap(addr, sb.st_size);
- close(fd);
- return TRUE;
-}
-
-METHOD(request_t, render, void,
- private_request_t *this, char *template)
-{
- NEOERR* err;
-
- thread_this->set(thread_this, this);
- err = cgi_display(this->cgi, template);
- if (err)
- {
- cgi_neo_error(this->cgi, err);
- nerr_log_error(err);
- }
-}
-
-METHOD(request_t, streamf, int,
- private_request_t *this, char *format, ...)
-{
- va_list args;
- int written;
-
- va_start(args, format);
- written = FCGX_VFPrintF(this->req.out, format, args);
- va_end(args);
- if (written >= 0 &&
- FCGX_FFlush(this->req.out) == -1)
- {
- return -1;
- }
- return written;
-}
-
-METHOD(request_t, set, void,
- private_request_t *this, char *key, char *value)
-{
- hdf_set_value(this->hdf, key, value);
-}
-
-METHOD(request_t, setf, void,
- private_request_t *this, char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- hdf_set_valuevf(this->hdf, format, args);
- va_end(args);
-}
-
-METHOD(request_t, get_ref, request_t*,
- private_request_t *this)
-{
- ref_get(&this->ref);
- return &this->public;
-}
-
-METHOD(request_t, destroy, void,
- private_request_t *this)
-{
- if (ref_put(&this->ref))
- {
- thread_this->set(thread_this, this);
- cgi_destroy(&this->cgi);
- FCGX_Finish_r(&this->req);
- free(this);
- }
-}
-
-/**
- * This initialization method is guaranteed to run only once
- * for all threads.
- */
-static void init(void)
-{
- cgiwrap_init_emu(NULL, read_cb, writef_cb, write_cb,
- getenv_cb, putenv_cb, iterenv_cb);
- thread_this = thread_value_create(NULL);
-}
-
-/*
- * see header file
- */
-request_t *request_create(int fd, bool debug)
-{
- NEOERR* err;
- private_request_t *this;
- bool failed = FALSE;
-
- INIT(this,
- .public = {
- .get_path = _get_path,
- .get_base = _get_base,
- .get_host = _get_host,
- .get_user_agent = _get_user_agent,
- .add_cookie = _add_cookie,
- .get_cookie = _get_cookie,
- .get_query_data = _get_query_data,
- .get_env_var = _get_env_var,
- .read_data = _read_data,
- .session_closed = _session_closed,
- .close_session = _close_session,
- .redirect = _redirect,
- .get_referer = _get_referer,
- .to_referer = _to_referer,
- .render = _render,
- .streamf = _streamf,
- .serve = _serve,
- .sendfile = _sendfile,
- .set = _set,
- .setf = _setf,
- .get_ref = _get_ref,
- .destroy = _destroy,
- },
- .ref = 1,
- );
-
- thread_cleanup_push(free, this);
- if (FCGX_InitRequest(&this->req, fd, 0) != 0 ||
- FCGX_Accept_r(&this->req) != 0)
- {
- failed = TRUE;
- }
- thread_cleanup_pop(failed);
- if (failed)
- {
- return NULL;
- }
-
- pthread_once(&once, init);
- thread_this->set(thread_this, this);
-
- while (this->req.envp[this->req_env_len] != NULL)
- {
- this->req_env_len++;
- }
-
- err = hdf_init(&this->hdf);
- if (!err)
- {
- hdf_set_value(this->hdf, "base", get_base(this));
- hdf_set_value(this->hdf, "Config.NoCache", "true");
- if (!debug)
- {
- hdf_set_value(this->hdf, "Config.TimeFooter", "0");
- hdf_set_value(this->hdf, "Config.CompressionEnabled", "1");
- hdf_set_value(this->hdf, "Config.WhiteSpaceStrip", "2");
- }
-
- err = cgi_init(&this->cgi, this->hdf);
- if (!err)
- {
- err = cgi_parse(this->cgi);
- if (!err)
- {
- return &this->public;
- }
- cgi_destroy(&this->cgi);
- }
- }
- nerr_log_error(err);
- FCGX_Finish_r(&this->req);
- free(this);
- return NULL;
-}
-
+++ /dev/null
-/*
- * 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.
- */
-
-/**
- * @defgroup request request
- * @{ @ingroup libfast
- */
-
-#ifndef REQUEST_H_
-#define REQUEST_H_
-
-#include <fcgiapp.h>
-#include <library.h>
-
-typedef struct request_t request_t;
-
-/**
- * A HTTP request, encapsulates FCGX_Request.
- *
- * The response is also handled through the request object.
- */
-struct request_t {
-
- /**
- * Add a cookie to the reply (Set-Cookie header).
- *
- * @param name name of the cookie to set
- * @param value value of the cookie
- */
- void (*add_cookie)(request_t *this, char *name, char *value);
-
- /**
- * 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);
-
- /**
- * Get the request path relative to the application.
- *
- * @return path
- */
- char* (*get_path)(request_t *this);
-
- /**
- * Get the base path of the application.
- *
- * @return base path
- */
- char* (*get_base)(request_t *this);
-
- /**
- * Get the remote host address of this request.
- *
- * @return host address as string
- */
- char* (*get_host)(request_t *this);
-
- /**
- * Get the user agent string.
- *
- * @return user agent string
- */
- char* (*get_user_agent)(request_t *this);
-
- /**
- * Get a post/get variable included in the request.
- *
- * @param name name of the POST/GET variable
- * @return value, NULL if not found
- */
- char* (*get_query_data)(request_t *this, char *name);
-
- /**
- * Get an arbitrary environment variable.
- *
- * @param name name of the environment variable
- * @return value, NULL if not found
- */
- char* (*get_env_var)(request_t *this, char *name);
-
- /**
- * Read raw POST/PUT data from HTTP request.
- *
- * @param buf buffer to read data into
- * @param len size of the supplied buffer
- * @return number of bytes read, < 0 on error
- */
- int (*read_data)(request_t *this, char *buf, int len);
-
- /**
- * Close the session and it's context after handling.
- */
- void (*close_session)(request_t *this);
-
- /**
- * Has the session been closed by close_session()?
- *
- * @return TRUE if session has been closed
- */
- bool (*session_closed)(request_t *this);
-
- /**
- * Redirect the client to another location.
- *
- * @param fmt location format string
- * @param ... variable argument for fmt
- */
- void (*redirect)(request_t *this, char *fmt, ...);
-
- /**
- * Get the HTTP referer.
- *
- * @return HTTP referer
- */
- char* (*get_referer)(request_t *this);
-
- /**
- * Redirect back to the referer.
- */
- void (*to_referer)(request_t *this);
-
- /**
- * Set a template value.
- *
- * @param key key to set
- * @param value value to set key to
- */
- void (*set)(request_t *this, char *key, char *value);
-
- /**
- * 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)(request_t *this, char *format, ...);
-
- /**
- * Render a template.
- *
- * The render() function additionally sets a HDF variable "base"
- * which points to the root of the web application and allows to point to
- * other targets without to worry about path location.
- *
- * @param template clearsilver template file location
- */
- void (*render)(request_t *this, char *template);
-
- /**
- * Stream a format string to the client.
- *
- * Stream is not closed and may be called multiple times to allow
- * server-push functionality.
- *
- * @param format printf like format string
- * @param ... argmuent list to format string
- * @return number of streamed bytes, < 0 if stream closed
- */
- int (*streamf)(request_t *this, char *format, ...);
-
- /**
- * Serve a request with headers and a body.
- *
- * @param headers HTTP headers, \n separated
- * @param chunk body to write to output
- */
- void (*serve)(request_t *this, char *headers, chunk_t chunk);
-
- /**
- * Send a file from the file system.
- *
- * @param path path to file to serve
- * @param mime mime type of file to send, or NULL
- * @return TRUE if file served successfully
- */
- bool (*sendfile)(request_t *this, char *path, char *mime);
-
- /**
- * Increase the reference count to the stream.
- *
- * @return this with increased refcount
- */
- request_t* (*get_ref)(request_t *this);
-
- /**
- * Destroy the request_t.
- */
- void (*destroy) (request_t *this);
-};
-
-/**
- * Create a request from the fastcgi struct.
- *
- * @param fd file descripter opened with FCGX_OpenSocket
- * @param debug no stripping, no compression, timing information
- */
-request_t *request_create(int fd, bool debug);
-
-#endif /** REQUEST_H_ @}*/
+++ /dev/null
-/*
- * 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 <collections/linked_list.h>
-
-#define COOKIE_LEN 16
-
-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[COOKIE_LEN * 2 + 1];
-
- /**
- * have we sent the session cookie?
- */
- bool cookie_sent;
-
- /**
- * list of controller instances controller_t
- */
- linked_list_t *controllers;
-
- /**
- * list of filter instances filter_t
- */
- linked_list_t *filters;
-
- /**
- * user defined session context
- */
- context_t *context;
-};
-
-METHOD(session_t, add_controller, void,
- private_session_t *this, controller_t *controller)
-{
- this->controllers->insert_last(this->controllers, controller);
-}
-
-METHOD(session_t, add_filter, void,
- private_session_t *this, filter_t *filter)
-{
- this->filters->insert_last(this->filters, filter);
-}
-
-/**
- * Create a session ID and a cookie
- */
-static bool create_sid(private_session_t *this)
-{
- char buf[COOKIE_LEN];
- rng_t *rng;
-
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
- {
- return FALSE;
- }
- if (!rng->get_bytes(rng, sizeof(buf), buf))
- {
- rng->destroy(rng);
- return FALSE;
- }
- rng->destroy(rng);
- chunk_to_hex(chunk_create(buf, sizeof(buf)), this->sid, FALSE);
- return TRUE;
-}
-
-/**
- * run all registered filters
- */
-static bool run_filter(private_session_t *this, request_t *request, char *p0,
- char *p1, char *p2, char *p3, char *p4, char *p5)
-{
- enumerator_t *enumerator;
- filter_t *filter;
-
- enumerator = this->filters->create_enumerator(this->filters);
- while (enumerator->enumerate(enumerator, &filter))
- {
- if (!filter->run(filter, request, p0, p1, p2, p3, p4, p5))
- {
- enumerator->destroy(enumerator);
- return FALSE;
- }
- }
- enumerator->destroy(enumerator);
- return TRUE;
-}
-
-METHOD(session_t, process, void,
- private_session_t *this, request_t *request)
-{
- char *pos, *start, *param[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
- enumerator_t *enumerator;
- bool handled = FALSE;
- controller_t *current;
- int i = 0;
-
- if (!this->cookie_sent)
- {
- request->add_cookie(request, "SID", this->sid);
- this->cookie_sent = TRUE;
- }
-
- start = request->get_path(request);
- if (start)
- {
- if (*start == '/')
- {
- start++;
- }
- while ((pos = strchr(start, '/')) != NULL && i < 5)
- {
- param[i++] = strndupa(start, pos - start);
- start = pos + 1;
- }
- param[i] = strdupa(start);
-
- if (run_filter(this, request, param[0], param[1], param[2], param[3],
- param[4], param[5]))
- {
- enumerator = this->controllers->create_enumerator(this->controllers);
- while (enumerator->enumerate(enumerator, ¤t))
- {
- if (streq(current->get_name(current), param[0]))
- {
- current->handle(current, request, param[1], param[2],
- param[3], param[4], param[5]);
- handled = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
- }
- else
- {
- handled = TRUE;
- }
- }
- if (!handled)
- {
- if (this->controllers->get_first(this->controllers,
- (void**)¤t) == SUCCESS)
- {
- request->streamf(request,
- "Status: 301 Moved permanently\nLocation: %s/%s\n\n",
- request->get_base(request), current->get_name(current));
- }
- }
-}
-
-METHOD(session_t, get_sid, char*,
- private_session_t *this)
-{
- return this->sid;
-}
-
-METHOD(session_t, destroy, void,
- private_session_t *this)
-{
- this->controllers->destroy_offset(this->controllers, offsetof(controller_t, destroy));
- this->filters->destroy_offset(this->filters, offsetof(filter_t, destroy));
- DESTROY_IF(this->context);
- free(this);
-}
-
-/*
- * see header file
- */
-session_t *session_create(context_t *context)
-{
- private_session_t *this;
-
- INIT(this,
- .public = {
- .add_controller = _add_controller,
- .add_filter = _add_filter,
- .process = _process,
- .get_sid = _get_sid,
- .destroy = _destroy,
- },
- .controllers = linked_list_create(),
- .filters = linked_list_create(),
- .context = context,
- );
- if (!create_sid(this))
- {
- destroy(this);
- return NULL;
- }
-
- return &this->public;
-}
-
+++ /dev/null
-/*
- * 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.
- */
-
-/**
- * @defgroup session session
- * @{ @ingroup libfast
- */
-
-#ifndef SESSION_H_
-#define SESSION_H_
-
-#include "request.h"
-#include "controller.h"
-#include "filter.h"
-
-typedef struct session_t session_t;
-
-/**
- * Session handling class, instanciated for each user session.
- */
-struct session_t {
-
- /**
- * Get the session ID of the session.
- *
- * @return session ID
- */
- char* (*get_sid)(session_t *this);
-
- /**
- * Add a controller instance to the session.
- *
- * @param controller controller to add
- */
- void (*add_controller)(session_t *this, controller_t *controller);
-
- /**
- * Add a filter instance to the session.
- *
- * @param filter filter to add
- */
- void (*add_filter)(session_t *this, filter_t *filter);
-
- /**
- * Process a request in this session.
- *
- * @param request request to process
- */
- void (*process)(session_t *this, request_t *request);
-
- /**
- * Destroy the session_t.
- */
- void (*destroy) (session_t *this);
-};
-
-/**
- * Create a session new session.
- *
- * @param context user defined session context instance
- * @return client session, NULL on error
- */
-session_t *session_create(context_t *context);
-
-#endif /** SESSION_H_ @}*/
+++ /dev/null
-/*
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
- *
- * 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 "smtp.h"
-
-#include <unistd.h>
-#include <errno.h>
-
-#include <utils/debug.h>
-
-typedef struct private_smtp_t private_smtp_t;
-
-/**
- * Private data of an smtp_t object.
- */
-struct private_smtp_t {
-
- /**
- * Public smtp_t interface.
- */
- smtp_t public;
-
- /**
- * file stream to SMTP server
- */
- FILE *f;
-};
-
-/**
- * Read the response code from an SMTP server
- */
-static int read_response(private_smtp_t *this)
-{
- char buf[256], *end;
- int res = 0;
-
- while (TRUE)
- {
- if (!fgets(buf, sizeof(buf), this->f))
- {
- return 0;
- }
- res = strtol(buf, &end, 10);
- switch (*end)
- {
- case '-':
- continue;
- case ' ':
- case '\0':
- case '\n':
- break;
- default:
- return 0;
- }
- break;
- }
- return res;
-}
-
-/**
- * write a SMTP command to the server, read response code
- */
-static int write_cmd(private_smtp_t *this, char *fmt, ...)
-{
- char buf[256];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
-
- if (fprintf(this->f, "%s\n", buf) < 1)
- {
- DBG1(DBG_LIB, "sending SMTP command failed");
- return 0;
- }
- return read_response(this);
-}
-
-METHOD(smtp_t, send_mail, bool,
- private_smtp_t *this, char *from, char *to, char *subject, char *fmt, ...)
-{
- va_list args;
-
- if (write_cmd(this, "MAIL FROM:<%s>", from) != 250)
- {
- DBG1(DBG_LIB, "SMTP MAIL FROM failed");
- return FALSE;
- }
- if (write_cmd(this, "RCPT TO:<%s>", to) != 250)
- {
- DBG1(DBG_LIB, "SMTP RCPT TO failed");
- return FALSE;
- }
- if (write_cmd(this, "DATA") != 354)
- {
- DBG1(DBG_LIB, "SMTP DATA failed");
- return FALSE;
- }
-
- fprintf(this->f, "From: %s\n", from);
- fprintf(this->f, "To: %s\n", to);
- fprintf(this->f, "Subject: %s\n", subject);
- fprintf(this->f, "\n");
- va_start(args, fmt);
- vfprintf(this->f, fmt, args);
- va_end(args);
- fprintf(this->f, "\n.\n");
- return read_response(this) == 250;
-}
-
-
-METHOD(smtp_t, destroy, void,
- private_smtp_t *this)
-{
- write_cmd(this, "QUIT");
- fclose(this->f);
- free(this);
-}
-
-/**
- * See header
- */
-smtp_t *smtp_create()
-{
- private_smtp_t *this;
- struct sockaddr_in addr = {
- .sin_family = AF_INET,
- .sin_port = htons(25),
- .sin_addr = {
- .s_addr = htonl(INADDR_LOOPBACK),
- },
- };
- int s;
-
- INIT(this,
- .public = {
- .send_mail = _send_mail,
- .destroy = _destroy,
- },
- );
-
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0)
- {
- DBG1(DBG_LIB, "opening SMTP socket failed: %s", strerror(errno));
- free(this);
- return NULL;
- }
- if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0)
- {
- DBG1(DBG_LIB, "connecting to SMTP server failed: %s", strerror(errno));
- close(s);
- free(this);
- return NULL;
- }
- this->f = fdopen(s, "a+");
- if (!this->f)
- {
- DBG1(DBG_LIB, "opening stream to SMTP server failed: %s",
- strerror(errno));
- close(s);
- free(this);
- return NULL;
- }
- if (read_response(this) != 220 ||
- write_cmd(this, "EHLO localhost") != 250)
- {
- DBG1(DBG_LIB, "SMTP EHLO failed");
- fclose(this->f);
- free(this);
- return NULL;
- }
- return &this->public;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
- *
- * 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.
- */
-
-/**
- * @defgroup smtp smtp
- * @{ @ingroup libfast
- */
-
-#ifndef SMTP_H_
-#define SMTP_H_
-
-typedef struct smtp_t smtp_t;
-
-#include <library.h>
-
-/**
- * Ultra-minimalistic SMTP client. Works at most with Exim on localhost.
- */
-struct smtp_t {
-
- /**
- * Send an e-mail message.
- *
- * @param from sender address
- * @param to recipient address
- * @param subject mail subject
- * @param fmt mail body format string
- * @param ... arguments for body format string
- */
- bool (*send_mail)(smtp_t *this, char *from, char *to,
- char *subject, char *fmt, ...);
-
- /**
- * Destroy a smtp_t.
- */
- void (*destroy)(smtp_t *this);
-};
-
-/**
- * Create a smtp instance.
- */
-smtp_t *smtp_create();
-
-#endif /** SMTP_H_ @}*/
manager_t *manager;
};
-static void login(private_auth_controller_t *this, request_t *request)
+static void login(private_auth_controller_t *this, fast_request_t *request)
{
request->set(request, "action", "check");
request->set(request, "title", "Login");
request->render(request, "templates/auth/login.cs");
}
-static void check(private_auth_controller_t *this, request_t *request)
+static void check(private_auth_controller_t *this, fast_request_t *request)
{
char *username, *password;
}
}
-static void logout(private_auth_controller_t *this, request_t *request)
+static void logout(private_auth_controller_t *this, fast_request_t *request)
{
this->manager->logout(this->manager);
request->redirect(request, "auth/login");
}
-METHOD(controller_t, get_name, char*,
+METHOD(fast_controller_t, get_name, char*,
private_auth_controller_t *this)
{
return "auth";
}
-METHOD(controller_t, handle, void,
- private_auth_controller_t *this, request_t *request, char *action,
+METHOD(fast_controller_t, handle, void,
+ private_auth_controller_t *this, fast_request_t *request, char *action,
char *p2, char *p3, char *p4, char *p5)
{
if (action)
request->redirect(request, "auth/login");
}
-METHOD(controller_t, destroy, void,
+METHOD(fast_controller_t, destroy, void,
private_auth_controller_t *this)
{
free(this);
/*
* see header file
*/
-controller_t *auth_controller_create(context_t *context, void *param)
+fast_controller_t *auth_controller_create(fast_context_t *context, void *param)
{
private_auth_controller_t *this;
return &this->public.controller;
}
-
#ifndef AUTH_CONTROLLER_H_
#define AUTH_CONTROLLER_H_
-
-#include <controller.h>
+#include <fast_controller.h>
typedef struct auth_controller_t auth_controller_t;
/**
* Implements controller_t interface.
*/
- controller_t controller;
+ fast_controller_t controller;
};
/**
* Create a auth_controller controller instance.
*/
-controller_t *auth_controller_create(context_t *context, void *param);
+fast_controller_t *auth_controller_create(fast_context_t *context, void *param);
#endif /** AUTH_CONTROLLER_H_ @}*/
* read XML of a peerconfig element and fill template
*/
static void process_peerconfig(private_config_controller_t *this,
- enumerator_t *e, request_t *r)
+ enumerator_t *e, fast_request_t *r)
{
xml_t *xml;
enumerator_t *e1, *e2, *e3;
}
}
-static void list(private_config_controller_t *this, request_t *r)
+static void list(private_config_controller_t *this, fast_request_t *r)
{
gateway_t *gateway;
xml_t *xml;
}
}
-METHOD(controller_t, get_name, char*,
+METHOD(fast_controller_t, get_name, char*,
private_config_controller_t *this)
{
return "config";
}
-METHOD(controller_t, handle, void,
- private_config_controller_t *this, request_t *request, char *action,
+METHOD(fast_controller_t, handle, void,
+ private_config_controller_t *this, fast_request_t *request, char *action,
char *p2, char *p3, char *p4, char *p5)
{
if (!this->manager->logged_in(this->manager))
return request->redirect(request, "config/list");
}
-METHOD(controller_t, destroy, void,
+METHOD(fast_controller_t, destroy, void,
private_config_controller_t *this)
{
free(this);
/*
* see header file
*/
-controller_t *config_controller_create(context_t *context, void *param)
+fast_controller_t *config_controller_create(fast_context_t *context,
+ void *param)
{
private_config_controller_t *this;
return &this->public.controller;
}
-
#ifndef CONFIG_CONTROLLER_H_
#define CONFIG_CONTROLLER_H_
-
-#include <controller.h>
+#include <fast_controller.h>
typedef struct config_controller_t config_controller_t;
/**
* Implements controller_t interface.
*/
- controller_t controller;
+ fast_controller_t controller;
};
/**
* Create a config_controller controller instance.
*/
-controller_t *config_controller_create(context_t *context, void *param);
+fast_controller_t *config_controller_create(fast_context_t *context,
+ void *param);
#endif /** CONFIG_CONTROLLER_H_ @}*/
/**
* handle the result of a control operation
*/
-static void handle_result(private_control_controller_t *this, request_t *r,
+static void handle_result(private_control_controller_t *this, fast_request_t *r,
enumerator_t *e)
{
enumerator_t *e1;
/**
* initiate an IKE or CHILD SA
*/
-static void initiate(private_control_controller_t *this, request_t *r,
+static void initiate(private_control_controller_t *this, fast_request_t *r,
bool ike, char *config)
{
gateway_t *gateway;
/**
* terminate an IKE or CHILD SA
*/
-static void terminate(private_control_controller_t *this, request_t *r,
+static void terminate(private_control_controller_t *this, fast_request_t *r,
bool ike, u_int32_t id)
{
gateway_t *gateway;
handle_result(this, r, e);
}
-METHOD(controller_t, get_name, char*,
+METHOD(fast_controller_t, get_name, char*,
private_control_controller_t *this)
{
return "control";
}
-METHOD(controller_t, handle, void,
- private_control_controller_t *this, request_t *request, char *action,
+METHOD(fast_controller_t, handle, void,
+ private_control_controller_t *this, fast_request_t *request, char *action,
char *str, char *p3, char *p4, char *p5)
{
if (!this->manager->logged_in(this->manager))
return request->redirect(request, "ikesa/list");
}
-METHOD(controller_t, destroy, void,
+METHOD(fast_controller_t, destroy, void,
private_control_controller_t *this)
{
free(this);
/*
* see header file
*/
-controller_t *control_controller_create(context_t *context, void *param)
+fast_controller_t *control_controller_create(fast_context_t *context,
+ void *param)
{
private_control_controller_t *this;
return &this->public.controller;
}
-
#ifndef CONTROL_CONTROLLER_H_
#define CONTROL_CONTROLLER_H_
-
-#include <controller.h>
+#include <fast_controller.h>
typedef struct control_controller_t control_controller_t;
/**
* Implements controller_t interface.
*/
- controller_t controller;
+ fast_controller_t controller;
};
/**
* Create a control_controller controller instance.
*/
-controller_t *control_controller_create(context_t *context, void *param);
+fast_controller_t *control_controller_create(fast_context_t *context,
+ void *param);
#endif /** CONTROL_CONTROLLER_H_ @}*/
};
-static void list(private_gateway_controller_t *this, request_t *request)
+static void list(private_gateway_controller_t *this, fast_request_t *request)
{
enumerator_t *enumerator;
char *name, *address;
request->render(request, "templates/gateway/list.cs");
}
-static void _select(private_gateway_controller_t *this, request_t *request)
+static void _select(private_gateway_controller_t *this, fast_request_t *request)
{
char *id;
request->redirect(request, "gateway/list");
}
-METHOD(controller_t, get_name, char*,
+METHOD(fast_controller_t, get_name, char*,
private_gateway_controller_t *this)
{
return "gateway";
}
-METHOD(controller_t, handle, void,
- private_gateway_controller_t *this, request_t *request, char *action,
+METHOD(fast_controller_t, handle, void,
+ private_gateway_controller_t *this, fast_request_t *request, char *action,
char *p2, char *p3, char *p4, char *p5)
{
if (!this->manager->logged_in(this->manager))
request->redirect(request, "gateway/list");
}
-METHOD(controller_t, destroy, void,
+METHOD(fast_controller_t, destroy, void,
private_gateway_controller_t *this)
{
free(this);
/*
* see header file
*/
-controller_t *gateway_controller_create(context_t *context, void *param)
+fast_controller_t *gateway_controller_create(fast_context_t *context,
+ void *param)
{
private_gateway_controller_t *this;
return &this->public.controller;
}
-
#ifndef GATEWAY_CONTROLLER_H_
#define GATEWAY_CONTROLLER_H_
-
-#include <controller.h>
+#include <fast_controller.h>
typedef struct gateway_controller_t gateway_controller_t;
/**
* Implements controller_t interface.
*/
- controller_t controller;
+ fast_controller_t controller;
};
/**
* Create a gateway_controller controller instance.
*/
-controller_t *gateway_controller_create(context_t *context, void *param);
+fast_controller_t *gateway_controller_create(fast_context_t *context,
+ void *param);
#endif /** GATEWAY_CONTROLLER_H_ @}*/
* read XML of a childsa element and fill template
*/
static void process_childsa(private_ikesa_controller_t *this, char *id,
- enumerator_t *e, request_t *r)
+ enumerator_t *e, fast_request_t *r)
{
xml_t *xml;
enumerator_t *e1, *e2;
* read XML of a ikesa element and fill template
*/
static void process_ikesa(private_ikesa_controller_t *this,
- enumerator_t *e, request_t *r)
+ enumerator_t *e, fast_request_t *r)
{
xml_t *xml;
enumerator_t *e1, *e2;
}
}
-static void list(private_ikesa_controller_t *this, request_t *r)
+static void list(private_ikesa_controller_t *this, fast_request_t *r)
{
gateway_t *gateway;
xml_t *xml;
}
}
-METHOD(controller_t, get_name, char*,
+METHOD(fast_controller_t, get_name, char*,
private_ikesa_controller_t *this)
{
return "ikesa";
}
-METHOD(controller_t, handle, void,
- private_ikesa_controller_t *this, request_t *request, char *action,
+METHOD(fast_controller_t, handle, void,
+ private_ikesa_controller_t *this, fast_request_t *request, char *action,
char *p2, char *p3, char *p4, char *p5)
{
if (!this->manager->logged_in(this->manager))
return request->redirect(request, "ikesa/list");
}
-METHOD(controller_t, destroy, void,
+METHOD(fast_controller_t, destroy, void,
private_ikesa_controller_t *this)
{
free(this);
/*
* see header file
*/
-controller_t *ikesa_controller_create(context_t *context, void *param)
+fast_controller_t *ikesa_controller_create(fast_context_t *context, void *param)
{
private_ikesa_controller_t *this;
return &this->public.controller;
}
-
#ifndef IKESA_CONTROLLER_H_
#define IKESA_CONTROLLER_H_
-
-#include <controller.h>
+#include <fast_controller.h>
typedef struct ikesa_controller_t ikesa_controller_t;
/**
* Implements controller_t interface.
*/
- controller_t controller;
+ fast_controller_t controller;
};
/**
* Create a ikesa_controller controller instance.
*/
-controller_t *ikesa_controller_create(context_t *context, void *param);
+fast_controller_t *ikesa_controller_create(fast_context_t *context, void *param);
#endif /** IKESA_CONTROLLER_H_ @}*/
* for more details.
*/
-#include <dispatcher.h>
+#include <fast_dispatcher.h>
#include <utils/debug.h>
#include <stdio.h>
int main (int arc, char *argv[])
{
- dispatcher_t *dispatcher;
+ fast_dispatcher_t *dispatcher;
storage_t *storage;
char *socket;
char *database;
{
DBG1(DBG_LIB, "database URI undefined, set manager.database "
"in strongswan.conf");
- return 1;
+ //return 1;
}
storage = storage_create(database);
return 1;
}
- dispatcher = dispatcher_create(socket, debug, timeout,
- (context_constructor_t)manager_create, storage);
+ dispatcher = fast_dispatcher_create(socket, debug, timeout,
+ (fast_context_constructor_t)manager_create, storage);
dispatcher->add_controller(dispatcher, ikesa_controller_create, NULL);
dispatcher->add_controller(dispatcher, gateway_controller_create, NULL);
dispatcher->add_controller(dispatcher, auth_controller_create, NULL);
return 0;
}
-
this->user = 0;
}
-METHOD(context_t, destroy, void,
+METHOD(fast_context_t, destroy, void,
private_manager_t *this)
{
if (this->gateway) this->gateway->destroy(this->gateway);
return &this->public;
}
-
#include "storage.h"
#include "gateway.h"
-#include <context.h>
+#include <fast_context.h>
typedef struct manager_t manager_t;
/**
* implements context_t interface
*/
- context_t context;
+ fast_context_t context;
/**
* Create an enumerator over all configured gateways.
/**
* list the configured peer configs
*/
-static void list(private_peer_controller_t *this, request_t *request)
+static void list(private_peer_controller_t *this, fast_request_t *request)
{
enumerator_t *query;
/**
* verify a peer alias
*/
-static bool verify_alias(private_peer_controller_t *this, request_t *request,
+static bool verify_alias(private_peer_controller_t *this, fast_request_t *request,
char *alias)
{
if (!alias || *alias == '\0')
* parse and verify a public key
*/
static bool parse_public_key(private_peer_controller_t *this,
- request_t *request, char *public_key,
+ fast_request_t *request, char *public_key,
chunk_t *encoding, chunk_t *keyid)
{
public_key_t *public;
/**
* register a new peer
*/
-static void add(private_peer_controller_t *this, request_t *request)
+static void add(private_peer_controller_t *this, fast_request_t *request)
{
char *alias = "", *public_key = "";
/**
* edit a peer
*/
-static void edit(private_peer_controller_t *this, request_t *request, int id)
+static void edit(private_peer_controller_t *this, fast_request_t *request, int id)
{
char *alias = "", *public_key = "", *pem;
chunk_t encoding, keyid;
/**
* delete a peer from the database
*/
-static void delete(private_peer_controller_t *this, request_t *request, int id)
+static void delete(private_peer_controller_t *this, fast_request_t *request, int id)
{
this->db->execute(this->db, NULL,
"DELETE FROM peer WHERE id = ? AND user = ?",
DB_INT, id, DB_UINT, this->user->get_user(this->user));
}
-METHOD(controller_t, get_name, char*,
+METHOD(fast_controller_t, get_name, char*,
private_peer_controller_t *this)
{
return "peer";
}
-METHOD(controller_t, handle, void,
- private_peer_controller_t *this, request_t *request, char *action,
+METHOD(fast_controller_t, handle, void,
+ private_peer_controller_t *this, fast_request_t *request, char *action,
char *idstr, char *p3, char *p4, char *p5)
{
if (action)
request->redirect(request, "peer/list");
}
-METHOD(controller_t, destroy, void,
+METHOD(fast_controller_t, destroy, void,
private_peer_controller_t *this)
{
free(this);
/*
* see header file
*/
-controller_t *peer_controller_create(user_t *user, database_t *db)
+fast_controller_t *peer_controller_create(user_t *user, database_t *db)
{
private_peer_controller_t *this;
return &this->public.controller;
}
-
#include <user.h>
-#include <controller.h>
+#include <fast_controller.h>
#include <database/database.h>
typedef struct peer_controller_t peer_controller_t;
/**
* Implements controller_t interface.
*/
- controller_t controller;
+ fast_controller_t controller;
};
/**
* Create a peer_controller controller instance.
*/
-controller_t *peer_controller_create(user_t *user, database_t *db);
+fast_controller_t *peer_controller_create(user_t *user, database_t *db);
#endif /** PEER_CONTROLLER_H_ @}*/
/**
* Login a user.
*/
-static void login(private_user_controller_t *this, request_t *request)
+static void login(private_user_controller_t *this, fast_request_t *request)
{
if (request->get_query_data(request, "submit"))
{
/**
* Logout a user.
*/
-static void logout(private_user_controller_t *this, request_t *request)
+static void logout(private_user_controller_t *this, fast_request_t *request)
{
request->redirect(request, "user/login");
request->close_session(request);
/**
* verify a user entered username for validity
*/
-static bool verify_login(private_user_controller_t *this, request_t *request,
- char *login)
+static bool verify_login(private_user_controller_t *this,
+ fast_request_t *request, char *login)
{
if (!login || *login == '\0')
{
/**
* verify a user entered password for validity
*/
-static bool verify_password(private_user_controller_t *this, request_t *request,
+static bool verify_password(private_user_controller_t *this,
+ fast_request_t *request,
char *password, char *confirm)
{
if (!password || *password == '\0')
/**
* Register a user.
*/
-static void add(private_user_controller_t *this, request_t *request)
+static void add(private_user_controller_t *this, fast_request_t *request)
{
char *login = "";
/**
* Edit the logged in user
*/
-static void edit(private_user_controller_t *this, request_t *request)
+static void edit(private_user_controller_t *this, fast_request_t *request)
{
enumerator_t *query;
char *old_login;
request->render(request, "templates/user/edit.cs");
}
-METHOD(controller_t, get_name, char*,
+METHOD(fast_controller_t, get_name, char*,
private_user_controller_t *this)
{
return "user";
}
-METHOD(controller_t, handle, void,
- private_user_controller_t *this, request_t *request, char *action,
+METHOD(fast_controller_t, handle, void,
+ private_user_controller_t *this, fast_request_t *request, char *action,
char *p2, char *p3, char *p4, char *p5)
{
if (action)
request->redirect(request, "user/login");
}
-METHOD(controller_t, destroy, void,
+METHOD(fast_controller_t, destroy, void,
private_user_controller_t *this)
{
free(this);
/*
* see header file
*/
-controller_t *user_controller_create(user_t *user, database_t *db)
+fast_controller_t *user_controller_create(user_t *user, database_t *db)
{
private_user_controller_t *this;
return &this->public.controller;
}
-
#include <user.h>
-#include <controller.h>
+#include <fast_controller.h>
#include <database/database.h>
typedef struct user_controller_t user_controller_t;
/**
* Implements controller_t interface.
*/
- controller_t controller;
+ fast_controller_t controller;
};
/**
* Create a user_controller controller instance.
*/
-controller_t *user_controller_create(user_t *user, database_t *db);
+fast_controller_t *user_controller_create(user_t *user, database_t *db);
#endif /** USER_CONTROLLER_H_ @}*/
database_t *db;
};
-METHOD(filter_t, run, bool,
- private_auth_filter_t *this, request_t *request, char *controller,
+METHOD(fast_filter_t, run, bool,
+ private_auth_filter_t *this, fast_request_t *request, char *controller,
char *action, char *p2, char *p3, char *p4, char *p5)
{
if (this->user->get_user(this->user))
return FALSE;
}
-METHOD(filter_t, destroy, void,
+METHOD(fast_filter_t, destroy, void,
private_auth_filter_t *this)
{
free(this);
/*
* see header file
*/
-filter_t *auth_filter_create(user_t *user, database_t *db)
+fast_filter_t *auth_filter_create(user_t *user, database_t *db)
{
private_auth_filter_t *this;
return &this->public.filter;
}
-
#define AUTH_FILTER_H_
#include <library.h>
-#include <filter.h>
+#include <fast_filter.h>
#include "user.h"
/**
* Implements filter_t interface.
*/
- filter_t filter;
+ fast_filter_t filter;
};
/**
* Create a auth_filter instance.
*/
-filter_t *auth_filter_create(user_t *user, database_t *db);
+fast_filter_t *auth_filter_create(user_t *user, database_t *db);
#endif /** AUTH_FILTER_H_ @}*/
#include <stdio.h>
-#include <dispatcher.h>
+#include <fast_dispatcher.h>
#include <utils/debug.h>
#include <database/database.h>
int main(int arc, char *argv[])
{
- dispatcher_t *dispatcher;
+ fast_dispatcher_t *dispatcher;
database_t *db;
char *socket;
bool debug;
return 1;
}
- dispatcher = dispatcher_create(socket, debug, timeout,
- (context_constructor_t)user_create, db);
+ dispatcher = fast_dispatcher_create(socket, debug, timeout,
+ (fast_context_constructor_t)user_create, db);
dispatcher->add_filter(dispatcher,
- (filter_constructor_t)auth_filter_create, db);
+ (fast_filter_constructor_t)auth_filter_create, db);
dispatcher->add_controller(dispatcher,
- (controller_constructor_t)user_controller_create, db);
+ (fast_controller_constructor_t)user_controller_create, db);
dispatcher->add_controller(dispatcher,
- (controller_constructor_t)peer_controller_create, db);
+ (fast_controller_constructor_t)peer_controller_create, db);
dispatcher->run(dispatcher, threads);
library_deinit();
return 0;
}
-
return this->user;
}
-METHOD(context_t, destroy, void,
+METHOD(fast_context_t, destroy, void,
private_user_t *this)
{
free(this);
return &this->public;
}
-
#ifndef USER_H_
#define USER_H_
-#include <context.h>
+#include <fast_context.h>
#include <library.h>
typedef struct user_t user_t;
/**
* implements context_t interface
*/
- context_t context;
+ fast_context_t context;
/**
* Set the user ID of the logged in user.