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:
+1
-34
@@ -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_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([cmd], [enable the command line IKE client charon-cmd.])
|
||||||
ARG_ENABL_SET([conftest], [enforce Suite B conformance test framework.])
|
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([fuzzing], [enable fuzzing scripts (found in directory fuzz).])
|
||||||
ARG_ENABL_SET([libipsec], [enable user space IPsec implementation.])
|
ARG_ENABL_SET([libipsec], [enable user space IPsec implementation.])
|
||||||
ARG_ENABL_SET([nm], [enable NetworkManager backend.])
|
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)
|
AC_SUBST(json_LIBS)
|
||||||
fi
|
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$mysql = xtrue; then
|
||||||
if test "x$windows" = xtrue; then
|
if test "x$windows" = xtrue; then
|
||||||
AC_CHECK_HEADER([mysql.h],,[AC_MSG_ERROR([MySQL header file mysql.h not found!])])
|
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_LEAK_DETECTIVE, test x$leak_detective = xtrue)
|
||||||
AM_CONDITIONAL(USE_LOCK_PROFILER, test x$lock_profiler = 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_ME, test x$mediation = xtrue)
|
||||||
AM_CONDITIONAL(USE_INTEGRITY_TEST, test x$integrity_test = xtrue)
|
AM_CONDITIONAL(USE_INTEGRITY_TEST, test x$integrity_test = xtrue)
|
||||||
AM_CONDITIONAL(USE_LOAD_WARNING, test x$load_warning = 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_SCRIPTS, test x$scripts = xtrue)
|
||||||
AM_CONDITIONAL(USE_FUZZING, test x$fuzzing = xtrue)
|
AM_CONDITIONAL(USE_FUZZING, test x$fuzzing = xtrue)
|
||||||
AM_CONDITIONAL(USE_CONFTEST, test x$conftest = 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_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_LIBIPSEC, test x$libipsec = xtrue)
|
||||||
AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = 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/Makefile
|
||||||
src/pki/man/Makefile
|
src/pki/man/Makefile
|
||||||
src/pool/Makefile
|
src/pool/Makefile
|
||||||
src/libfast/Makefile
|
|
||||||
src/checksum/Makefile
|
src/checksum/Makefile
|
||||||
src/conftest/Makefile
|
src/conftest/Makefile
|
||||||
src/pt-tls-client/Makefile
|
src/pt-tls-client/Makefile
|
||||||
|
|||||||
+1
-3
@@ -280,7 +280,7 @@ all|alpine|codeql|coverage|sonarcloud|no-dbg|no-testable-ke)
|
|||||||
CONFIG="$CONFIG --without-testable-ke"
|
CONFIG="$CONFIG --without-testable-ke"
|
||||||
fi
|
fi
|
||||||
DEPS="$DEPS libcurl4-gnutls-dev libsoup-3.0-dev libunbound-dev libldns-dev
|
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
|
libldap2-dev libpcsclite-dev libpam0g-dev binutils-dev libnm-dev
|
||||||
libgcrypt20-dev libjson-c-dev libtspi-dev libsystemd-dev
|
libgcrypt20-dev libjson-c-dev libtspi-dev libsystemd-dev
|
||||||
libselinux1-dev libiptc-dev ruby-rubygems python3-build tox"
|
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"
|
CONFIG="$CONFIG --disable-systemd --disable-cert-enroll-timer"
|
||||||
# no TrouSerS either
|
# no TrouSerS either
|
||||||
CONFIG="$CONFIG --disable-tss-trousers --disable-aikgen"
|
CONFIG="$CONFIG --disable-tss-trousers --disable-aikgen"
|
||||||
# and no Clearsilver
|
|
||||||
CONFIG="$CONFIG --disable-fast"
|
|
||||||
fi
|
fi
|
||||||
if test "$1" = "build-deps"; then
|
if test "$1" = "build-deps"; then
|
||||||
build_botan
|
build_botan
|
||||||
|
|||||||
@@ -87,10 +87,6 @@ if USE_CONFTEST
|
|||||||
SUBDIRS += conftest
|
SUBDIRS += conftest
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if USE_FAST
|
|
||||||
SUBDIRS += libfast
|
|
||||||
endif
|
|
||||||
|
|
||||||
if USE_ATTR_SQL
|
if USE_ATTR_SQL
|
||||||
SUBDIRS += pool
|
SUBDIRS += pool
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -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)
|
|
||||||
@@ -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_ @}*/
|
|
||||||
@@ -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_ @}*/
|
|
||||||
@@ -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, ¢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
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -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_ @}*/
|
|
||||||
@@ -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_ @} */
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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_ @}*/
|
|
||||||
@@ -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, ¤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;
|
|
||||||
}
|
|
||||||
@@ -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_ @}*/
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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_ @}*/
|
|
||||||
@@ -555,8 +555,6 @@ static char *whitelist[] = {
|
|||||||
"mysql_init_character_set",
|
"mysql_init_character_set",
|
||||||
"init_client_errs",
|
"init_client_errs",
|
||||||
"my_thread_init",
|
"my_thread_init",
|
||||||
/* fastcgi library */
|
|
||||||
"FCGX_Init",
|
|
||||||
/* libxml */
|
/* libxml */
|
||||||
"xmlInitCharEncodingHandlers",
|
"xmlInitCharEncodingHandlers",
|
||||||
"xmlInitParser",
|
"xmlInitParser",
|
||||||
@@ -566,8 +564,6 @@ static char *whitelist[] = {
|
|||||||
/* libldap */
|
/* libldap */
|
||||||
"ldap_int_initialize",
|
"ldap_int_initialize",
|
||||||
"ldap_pvt_tls_set_option",
|
"ldap_pvt_tls_set_option",
|
||||||
/* ClearSilver */
|
|
||||||
"nerr_init",
|
|
||||||
/* libgcrypt */
|
/* libgcrypt */
|
||||||
"gcrypt_plugin_create",
|
"gcrypt_plugin_create",
|
||||||
"gcry_control",
|
"gcry_control",
|
||||||
|
|||||||
Reference in New Issue
Block a user