libfast: Remove FastCGI application server library

The two users (manager, medsrv) are gone, so there is no reason to keep
this around.
This commit is contained in:
Tobias Brunner
2026-07-24 14:59:51 +02:00
parent ac690f1a5e
commit 60846f24bf
16 changed files with 2 additions and 2122 deletions
+1 -34
View File
@@ -287,7 +287,6 @@ ARG_ENABL_SET([aikgen], [enable AIK generator for TPM 1.2.])
ARG_DISBL_SET([charon], [disable the IKEv1/IKEv2 keying daemon charon.])
ARG_ENABL_SET([cmd], [enable the command line IKE client charon-cmd.])
ARG_ENABL_SET([conftest], [enforce Suite B conformance test framework.])
ARG_ENABL_SET([fast], [enable libfast (FastCGI Application Server w/ templates.])
ARG_ENABL_SET([fuzzing], [enable fuzzing scripts (found in directory fuzz).])
ARG_ENABL_SET([libipsec], [enable user space IPsec implementation.])
ARG_ENABL_SET([nm], [enable NetworkManager backend.])
@@ -1106,36 +1105,6 @@ if test x$imc_swima = xtrue -o x$imv_swima = xtrue; then
AC_SUBST(json_LIBS)
fi
if test x$fast = xtrue; then
AC_CHECK_LIB([neo_utl],[hdf_init],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_utl not found!])],[])
AC_MSG_CHECKING([for -lneo_cgi and dependencies])
saved_CFLAGS=$CFLAGS
saved_LIBS=$LIBS
LIBS="-lneo_cgi -lneo_cs -lneo_utl"
CFLAGS="-I/usr/include/ClearSilver"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <cgi/cgi.h>]],
[[NEOERR *err = cgi_display(NULL, NULL);]])],
[AC_MSG_RESULT([yes])],
[LIBS="$LIBS -lz";
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <cgi/cgi.h>]],
[[NEOERR *err = cgi_display(NULL, NULL);]])],
[AC_MSG_RESULT([yes, zlib required])],
[AC_MSG_ERROR([not found])]
)]
)
clearsilver_LIBS="$LIBS"
AC_SUBST(clearsilver_LIBS)
LIBS=$saved_LIBS
CFLAGS=$saved_CFLAGS
AC_CHECK_LIB([fcgi],[FCGX_Init],[LIBS="$LIBS"],[AC_MSG_ERROR([FastCGI library fcgi not found!])],[])
AC_CHECK_HEADER([fcgiapp.h],,[AC_MSG_ERROR([FastCGI header file fcgiapp.h not found!])])
fi
if test x$mysql = xtrue; then
if test "x$windows" = xtrue; then
AC_CHECK_HEADER([mysql.h],,[AC_MSG_ERROR([MySQL header file mysql.h not found!])])
@@ -1846,7 +1815,6 @@ AM_CONDITIONAL(USE_PF_HANDLER, test x$dhcp = xtrue -o x$farp = xtrue)
# ---------------
AM_CONDITIONAL(USE_LEAK_DETECTIVE, test x$leak_detective = xtrue)
AM_CONDITIONAL(USE_LOCK_PROFILER, test x$lock_profiler = xtrue)
AM_CONDITIONAL(USE_FAST, test x$fast = xtrue)
AM_CONDITIONAL(USE_ME, test x$mediation = xtrue)
AM_CONDITIONAL(USE_INTEGRITY_TEST, test x$integrity_test = xtrue)
AM_CONDITIONAL(USE_LOAD_WARNING, test x$load_warning = xtrue)
@@ -1861,7 +1829,7 @@ AM_CONDITIONAL(USE_PKI, test x$pki = xtrue)
AM_CONDITIONAL(USE_SCRIPTS, test x$scripts = xtrue)
AM_CONDITIONAL(USE_FUZZING, test x$fuzzing = xtrue)
AM_CONDITIONAL(USE_CONFTEST, test x$conftest = xtrue)
AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$pki = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$tls = xtrue -o x$tnc_tnccs = xtrue -o x$aikgen = xtrue -o x$svc = xtrue -o x$systemd = xtrue)
AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$pki = xtrue -o x$conftest = xtrue -o x$imcv = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$tls = xtrue -o x$tnc_tnccs = xtrue -o x$aikgen = xtrue -o x$svc = xtrue -o x$systemd = xtrue)
AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$svc = xtrue -o x$systemd = xtrue)
AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue)
AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue)
@@ -2162,7 +2130,6 @@ AC_CONFIG_FILES([
src/pki/Makefile
src/pki/man/Makefile
src/pool/Makefile
src/libfast/Makefile
src/checksum/Makefile
src/conftest/Makefile
src/pt-tls-client/Makefile
+1 -3
View File
@@ -280,7 +280,7 @@ all|alpine|codeql|coverage|sonarcloud|no-dbg|no-testable-ke)
CONFIG="$CONFIG --without-testable-ke"
fi
DEPS="$DEPS libcurl4-gnutls-dev libsoup-3.0-dev libunbound-dev libldns-dev
libmysqlclient-dev libsqlite3-dev clearsilver-dev libfcgi-dev
libmysqlclient-dev libsqlite3-dev
libldap2-dev libpcsclite-dev libpam0g-dev binutils-dev libnm-dev
libgcrypt20-dev libjson-c-dev libtspi-dev libsystemd-dev
libselinux1-dev libiptc-dev ruby-rubygems python3-build tox"
@@ -303,8 +303,6 @@ all|alpine|codeql|coverage|sonarcloud|no-dbg|no-testable-ke)
CONFIG="$CONFIG --disable-systemd --disable-cert-enroll-timer"
# no TrouSerS either
CONFIG="$CONFIG --disable-tss-trousers --disable-aikgen"
# and no Clearsilver
CONFIG="$CONFIG --disable-fast"
fi
if test "$1" = "build-deps"; then
build_botan
-4
View File
@@ -87,10 +87,6 @@ if USE_CONFTEST
SUBDIRS += conftest
endif
if USE_FAST
SUBDIRS += libfast
endif
if USE_ATTR_SQL
SUBDIRS += pool
else
-25
View File
@@ -1,25 +0,0 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
-I/usr/include/ClearSilver
AM_CFLAGS = \
$(PLUGIN_CFLAGS)
AM_LDFLAGS = \
-no-undefined
ipseclib_LTLIBRARIES = libfast.la
libfast_la_SOURCES = \
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 = \
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 \
-lfcgi $(clearsilver_LIBS) $(PTHREADLIB) $(ATOMICLIB)
-43
View File
@@ -1,43 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks 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_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_ @}*/
-79
View File
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks 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_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_ @}*/
-465
View File
@@ -1,465 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks 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_dispatcher.h"
#include "fast_request.h"
#include "fast_session.h"
#include <fcgiapp.h>
#include <signal.h>
#include <unistd.h>
#include <errno.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>
/** Interval 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;
/**
* Hashtable 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 instantiate 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);
if (!session)
{
return NULL;
}
enumerator = this->controllers->create_enumerator(this->controllers);
while (enumerator->enumerate(enumerator, &centry))
{
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
*/
CALLBACK(dispatch, void*,
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)
{
break;
}
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);
}
return NULL;
}
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(dispatch, this);
if (this->threads[threads - 1])
{
threads--;
}
}
}
METHOD(fast_dispatcher_t, waitsignal, void,
private_fast_dispatcher_t *this)
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGHUP);
sigprocmask(SIG_BLOCK, &set, NULL);
while (sigwaitinfo(&set, NULL) == -1 && errno == EINTR)
{
/* wait for signal */
}
}
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;
}
-138
View File
@@ -1,138 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks 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 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 threadsafe. Often a database wrapper is the global context.
* The session context is instantiated 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 instantiated. 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 instantiated 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 controller
* @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.
*
* Instantiate 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_ @}*/
-65
View File
@@ -1,65 +0,0 @@
/*
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks 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_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_ @} */
-492
View File
@@ -1,492 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks 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.
*/
#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/stat.h>
#include <fcntl.h>
#include <inttypes.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 threadsafe, 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)
{
chunk_t *data;
int written;
char buf[24];
data = chunk_map(path, FALSE);
if (!data)
{
return FALSE;
}
/* FCGX does not like large integers, print to a buffer using libc */
snprintf(buf, sizeof(buf), "%"PRId64, (int64_t)data->len);
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");
while (data->len)
{
written = FCGX_PutStr(data->ptr, data->len, this->req.out);
if (written == -1)
{
chunk_unmap(data);
return FALSE;
}
*data = chunk_skip(*data, written);
}
chunk_unmap(data);
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;
}
-218
View File
@@ -1,218 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks 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_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 ... argument 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 descriptor 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_ @}*/
-229
View File
@@ -1,229 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks 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.
*/
#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, &current))
{
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**)&current) == 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;
}
-78
View File
@@ -1,78 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
*
* Copyright (C) secunet Security Networks 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_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, instantiated 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_ @}*/
-188
View File
@@ -1,188 +0,0 @@
/*
* Copyright (C) 2010 Martin Willi
*
* Copyright (C) secunet Security Networks 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;
}
-57
View File
@@ -1,57 +0,0 @@
/*
* Copyright (C) 2010 Martin Willi
*
* Copyright (C) secunet Security Networks 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_ @}*/
-4
View File
@@ -555,8 +555,6 @@ static char *whitelist[] = {
"mysql_init_character_set",
"init_client_errs",
"my_thread_init",
/* fastcgi library */
"FCGX_Init",
/* libxml */
"xmlInitCharEncodingHandlers",
"xmlInitParser",
@@ -566,8 +564,6 @@ static char *whitelist[] = {
/* libldap */
"ldap_int_initialize",
"ldap_pvt_tls_set_option",
/* ClearSilver */
"nerr_init",
/* libgcrypt */
"gcrypt_plugin_create",
"gcry_control",