version 1.1.1.1, 2013/10/14 10:32:48
|
version 1.1.1.2, 2016/11/02 10:35:00
|
Line 1
|
Line 1
|
|
#include "first.h" |
|
|
#include "plugin.h" |
#include "plugin.h" |
#include "log.h" |
#include "log.h" |
|
|
Line 10
|
Line 12
|
# include <valgrind/valgrind.h> |
# include <valgrind/valgrind.h> |
#endif |
#endif |
|
|
#ifndef __WIN32 | #if !defined(__WIN32) && !defined(LIGHTTPD_STATIC) |
# include <dlfcn.h> |
# include <dlfcn.h> |
#endif |
#endif |
/* |
/* |
Line 29 typedef struct {
|
Line 31 typedef struct {
|
|
|
typedef enum { |
typedef enum { |
PLUGIN_FUNC_UNSET, |
PLUGIN_FUNC_UNSET, |
PLUGIN_FUNC_HANDLE_URI_CLEAN, |
|
PLUGIN_FUNC_HANDLE_URI_RAW, |
|
PLUGIN_FUNC_HANDLE_REQUEST_DONE, |
|
PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, |
|
PLUGIN_FUNC_HANDLE_TRIGGER, |
|
PLUGIN_FUNC_HANDLE_SIGHUP, |
|
PLUGIN_FUNC_HANDLE_SUBREQUEST, |
|
PLUGIN_FUNC_HANDLE_SUBREQUEST_START, |
|
PLUGIN_FUNC_HANDLE_JOBLIST, |
|
PLUGIN_FUNC_HANDLE_DOCROOT, |
|
PLUGIN_FUNC_HANDLE_PHYSICAL, |
|
PLUGIN_FUNC_CONNECTION_RESET, |
|
PLUGIN_FUNC_INIT, |
|
PLUGIN_FUNC_CLEANUP, |
|
PLUGIN_FUNC_SET_DEFAULTS, |
|
|
|
PLUGIN_FUNC_SIZEOF | PLUGIN_FUNC_HANDLE_URI_CLEAN, |
| PLUGIN_FUNC_HANDLE_URI_RAW, |
| PLUGIN_FUNC_HANDLE_REQUEST_DONE, |
| PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, |
| PLUGIN_FUNC_HANDLE_TRIGGER, |
| PLUGIN_FUNC_HANDLE_SIGHUP, |
| PLUGIN_FUNC_HANDLE_SUBREQUEST, |
| PLUGIN_FUNC_HANDLE_SUBREQUEST_START, |
| PLUGIN_FUNC_HANDLE_DOCROOT, |
| PLUGIN_FUNC_HANDLE_PHYSICAL, |
| PLUGIN_FUNC_CONNECTION_RESET, |
| PLUGIN_FUNC_INIT, |
| PLUGIN_FUNC_CLEANUP, |
| PLUGIN_FUNC_SET_DEFAULTS, |
| |
| PLUGIN_FUNC_SIZEOF |
} plugin_t; |
} plugin_t; |
|
|
static plugin *plugin_init(void) { |
static plugin *plugin_init(void) { |
plugin *p; |
plugin *p; |
|
|
p = calloc(1, sizeof(*p)); |
p = calloc(1, sizeof(*p)); |
|
force_assert(NULL != p); |
|
|
return p; |
return p; |
} |
} |
|
|
static void plugin_free(plugin *p) { |
static void plugin_free(plugin *p) { |
|
#if !defined(LIGHTTPD_STATIC) |
int use_dlclose = 1; |
int use_dlclose = 1; |
|
#endif |
|
|
if (p->name) buffer_free(p->name); |
if (p->name) buffer_free(p->name); |
#ifdef HAVE_VALGRIND_VALGRIND_H | #if defined(HAVE_VALGRIND_VALGRIND_H) && !defined(LIGHTTPD_STATIC) |
/*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/ |
/*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/ |
#endif |
#endif |
|
|
#ifndef LIGHTTPD_STATIC | #if !defined(LIGHTTPD_STATIC) |
if (use_dlclose && p->lib) { |
if (use_dlclose && p->lib) { |
#ifdef __WIN32 | #if defined(__WIN32) |
FreeLibrary(p->lib); | ) FreeLibrary(p->lib); |
#else |
#else |
dlclose(p->lib); |
dlclose(p->lib); |
#endif |
#endif |
Line 81 static int plugins_register(server *srv, plugin *p) {
|
Line 87 static int plugins_register(server *srv, plugin *p) {
|
if (0 == srv->plugins.size) { |
if (0 == srv->plugins.size) { |
srv->plugins.size = 4; |
srv->plugins.size = 4; |
srv->plugins.ptr = malloc(srv->plugins.size * sizeof(*ps)); |
srv->plugins.ptr = malloc(srv->plugins.size * sizeof(*ps)); |
|
force_assert(NULL != srv->plugins.ptr); |
srv->plugins.used = 0; |
srv->plugins.used = 0; |
} else if (srv->plugins.used == srv->plugins.size) { |
} else if (srv->plugins.used == srv->plugins.size) { |
srv->plugins.size += 4; |
srv->plugins.size += 4; |
srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps)); |
srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps)); |
|
force_assert(NULL != srv->plugins.ptr); |
} |
} |
|
|
ps = srv->plugins.ptr; |
ps = srv->plugins.ptr; |
Line 99 static int plugins_register(server *srv, plugin *p) {
|
Line 107 static int plugins_register(server *srv, plugin *p) {
|
* |
* |
*/ |
*/ |
|
|
#ifdef LIGHTTPD_STATIC | #if defined(LIGHTTPD_STATIC) |
int plugins_load(server *srv) { | |
plugin *p; | /* pre-declare functions, as there is no header for them */ |
#define PLUGIN_INIT(x)\ |
#define PLUGIN_INIT(x)\ |
p = plugin_init(); \ | int x ## _plugin_init(plugin *p); |
if (x ## _plugin_init(p)) { \ | |
log_error_write(srv, __FILE__, __LINE__, "ss", #x, "plugin init failed" ); \ | |
plugin_free(p); \ | |
return -1;\ | |
}\ | |
plugins_register(srv, p); | |
|
|
#include "plugin-static.h" |
#include "plugin-static.h" |
|
|
|
#undef PLUGIN_INIT |
|
|
|
/* build NULL-terminated table of name + init-function */ |
|
|
|
typedef struct { |
|
const char* name; |
|
int (*plugin_init)(plugin *p); |
|
} plugin_load_functions; |
|
|
|
static const plugin_load_functions load_functions[] = { |
|
#define PLUGIN_INIT(x) \ |
|
{ #x, &x ## _plugin_init }, |
|
|
|
#include "plugin-static.h" |
|
|
|
{ NULL, NULL } |
|
#undef PLUGIN_INIT |
|
}; |
|
|
|
int plugins_load(server *srv) { |
|
plugin *p; |
|
size_t i, j; |
|
|
|
for (i = 0; i < srv->srvconf.modules->used; i++) { |
|
data_string *d = (data_string *)srv->srvconf.modules->data[i]; |
|
char *module = d->value->ptr; |
|
|
|
for (j = 0; j < i; j++) { |
|
if (buffer_is_equal(d->value, ((data_string *) srv->srvconf.modules->data[j])->value)) { |
|
log_error_write(srv, __FILE__, __LINE__, "sbs", |
|
"Cannot load plugin", d->value, |
|
"more than once, please fix your config (lighttpd may not accept such configs in future releases)"); |
|
continue; |
|
} |
|
} |
|
|
|
for (j = 0; load_functions[j].name; ++j) { |
|
if (0 == strcmp(load_functions[j].name, module)) { |
|
p = plugin_init(); |
|
if ((*load_functions[j].plugin_init)(p)) { |
|
log_error_write(srv, __FILE__, __LINE__, "ss", module, "plugin init failed" ); |
|
plugin_free(p); |
|
return -1; |
|
} |
|
plugins_register(srv, p); |
|
break; |
|
} |
|
} |
|
if (!load_functions[j].name) { |
|
log_error_write(srv, __FILE__, __LINE__, "ss", module, " plugin not found" ); |
|
return -1; |
|
} |
|
} |
|
|
return 0; |
return 0; |
} |
} |
#else | #else /* defined(LIGHTTPD_STATIC) */ |
int plugins_load(server *srv) { |
int plugins_load(server *srv) { |
plugin *p; |
plugin *p; |
int (*init)(plugin *pl); |
int (*init)(plugin *pl); |
const char *error; |
|
size_t i, j; |
size_t i, j; |
|
|
for (i = 0; i < srv->srvconf.modules->used; i++) { |
for (i = 0; i < srv->srvconf.modules->used; i++) { |
data_string *d = (data_string *)srv->srvconf.modules->data[i]; |
data_string *d = (data_string *)srv->srvconf.modules->data[i]; |
char *modules = d->value->ptr; | char *module = d->value->ptr; |
|
|
for (j = 0; j < i; j++) { |
for (j = 0; j < i; j++) { |
if (buffer_is_equal(d->value, ((data_string *) srv->srvconf.modules->data[j])->value)) { |
if (buffer_is_equal(d->value, ((data_string *) srv->srvconf.modules->data[j])->value)) { |
log_error_write(srv, __FILE__, __LINE__, "sbs", "Cannot load plugin", d->value, "more than once, please fix your config (we may not accept such configs in future releases"); | log_error_write(srv, __FILE__, __LINE__, "sbs", |
| "Cannot load plugin", d->value, |
| "more than once, please fix your config (lighttpd may not accept such configs in future releases)"); |
continue; |
continue; |
} |
} |
} |
} |
|
|
buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir); | buffer_copy_buffer(srv->tmp_buf, srv->srvconf.modules_dir); |
|
|
buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("/")); |
buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("/")); |
buffer_append_string(srv->tmp_buf, modules); | buffer_append_string(srv->tmp_buf, module); |
#if defined(__WIN32) || defined(__CYGWIN__) |
#if defined(__WIN32) || defined(__CYGWIN__) |
buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".dll")); |
buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".dll")); |
#else |
#else |
Line 148 int plugins_load(server *srv) {
|
Line 205 int plugins_load(server *srv) {
|
if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) { |
if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) { |
LPVOID lpMsgBuf; |
LPVOID lpMsgBuf; |
FormatMessage( |
FormatMessage( |
FORMAT_MESSAGE_ALLOCATE_BUFFER | | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
FORMAT_MESSAGE_FROM_SYSTEM, | FORMAT_MESSAGE_FROM_SYSTEM, |
NULL, | NULL, |
GetLastError(), | GetLastError(), |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
(LPTSTR) &lpMsgBuf, | (LPTSTR) &lpMsgBuf, |
0, NULL ); | 0, NULL); |
|
|
log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed", |
log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed", |
lpMsgBuf, srv->tmp_buf); | lpMsgBuf, srv->tmp_buf); |
|
|
plugin_free(p); |
plugin_free(p); |
|
|
Line 167 int plugins_load(server *srv) {
|
Line 224 int plugins_load(server *srv) {
|
#else |
#else |
if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_NOW|RTLD_GLOBAL))) { |
if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_NOW|RTLD_GLOBAL))) { |
log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:", |
log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:", |
srv->tmp_buf, dlerror()); | srv->tmp_buf, dlerror()); |
|
|
plugin_free(p); |
plugin_free(p); |
|
|
Line 176 int plugins_load(server *srv) {
|
Line 233 int plugins_load(server *srv) {
|
|
|
#endif |
#endif |
buffer_reset(srv->tmp_buf); |
buffer_reset(srv->tmp_buf); |
buffer_copy_string(srv->tmp_buf, modules); | buffer_copy_string(srv->tmp_buf, module); |
buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("_plugin_init")); |
buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("_plugin_init")); |
|
|
#ifdef __WIN32 |
#ifdef __WIN32 |
init = GetProcAddress(p->lib, srv->tmp_buf->ptr); |
init = GetProcAddress(p->lib, srv->tmp_buf->ptr); |
|
|
if (init == NULL) { | if (init == NULL) { |
LPVOID lpMsgBuf; |
LPVOID lpMsgBuf; |
FormatMessage( |
FormatMessage( |
FORMAT_MESSAGE_ALLOCATE_BUFFER | | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
FORMAT_MESSAGE_FROM_SYSTEM, | FORMAT_MESSAGE_FROM_SYSTEM, |
NULL, | NULL, |
GetLastError(), | GetLastError(), |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
(LPTSTR) &lpMsgBuf, | (LPTSTR) &lpMsgBuf, |
0, NULL ); | 0, NULL); |
|
|
log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf); |
log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf); |
|
|
Line 205 int plugins_load(server *srv) {
|
Line 262 int plugins_load(server *srv) {
|
#else |
#else |
*(void **)(&init) = dlsym(p->lib, srv->tmp_buf->ptr); |
*(void **)(&init) = dlsym(p->lib, srv->tmp_buf->ptr); |
#endif |
#endif |
if ((error = dlerror()) != NULL) { | if (NULL == init) { |
log_error_write(srv, __FILE__, __LINE__, "s", error); | const char *error = dlerror(); |
| if (error != NULL) { |
| log_error_write(srv, __FILE__, __LINE__, "ss", "dlsym:", error); |
| } else { |
| log_error_write(srv, __FILE__, __LINE__, "ss", "dlsym symbol not found:", srv->tmp_buf->ptr); |
| } |
|
|
plugin_free(p); |
plugin_free(p); |
return -1; |
return -1; |
Line 214 int plugins_load(server *srv) {
|
Line 276 int plugins_load(server *srv) {
|
|
|
#endif |
#endif |
if ((*init)(p)) { |
if ((*init)(p)) { |
log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" ); | log_error_write(srv, __FILE__, __LINE__, "ss", module, "plugin init failed" ); |
|
|
plugin_free(p); |
plugin_free(p); |
return -1; |
return -1; |
} |
} |
#if 0 |
#if 0 |
log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" ); | log_error_write(srv, __FILE__, __LINE__, "ss", module, "plugin loaded" ); |
#endif |
#endif |
plugins_register(srv, p); |
plugins_register(srv, p); |
} |
} |
|
|
return 0; |
return 0; |
} |
} |
#endif | #endif /* defined(LIGHTTPD_STATIC) */ |
|
|
#define PLUGIN_TO_SLOT(x, y) \ |
#define PLUGIN_TO_SLOT(x, y) \ |
handler_t plugins_call_##y(server *srv, connection *con) {\ |
handler_t plugins_call_##y(server *srv, connection *con) {\ |
plugin **slot;\ |
plugin **slot;\ |
size_t j;\ |
size_t j;\ |
if (!srv->plugin_slots) return HANDLER_GO_ON;\ | if (!srv->plugin_slots) return HANDLER_GO_ON;\ |
slot = ((plugin ***)(srv->plugin_slots))[x];\ | slot = ((plugin ***)(srv->plugin_slots))[x];\ |
if (!slot) return HANDLER_GO_ON;\ |
if (!slot) return HANDLER_GO_ON;\ |
for (j = 0; j < srv->plugins.used && slot[j]; j++) { \ |
for (j = 0; j < srv->plugins.used && slot[j]; j++) { \ |
plugin *p = slot[j];\ |
plugin *p = slot[j];\ |
Line 270 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle
|
Line 332 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle
|
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist) |
|
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset) |
PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset) |
Line 281 PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connectio
|
Line 342 PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connectio
|
handler_t plugins_call_##y(server *srv) {\ |
handler_t plugins_call_##y(server *srv) {\ |
plugin **slot;\ |
plugin **slot;\ |
size_t j;\ |
size_t j;\ |
if (!srv->plugin_slots) return HANDLER_GO_ON;\ | if (!srv->plugin_slots) return HANDLER_GO_ON;\ |
slot = ((plugin ***)(srv->plugin_slots))[x];\ | slot = ((plugin ***)(srv->plugin_slots))[x];\ |
if (!slot) return HANDLER_GO_ON;\ |
if (!slot) return HANDLER_GO_ON;\ |
for (j = 0; j < srv->plugins.used && slot[j]; j++) { \ |
for (j = 0; j < srv->plugins.used && slot[j]; j++) { \ |
plugin *p = slot[j];\ |
plugin *p = slot[j];\ |
Line 369 handler_t plugins_call_init(server *srv) {
|
Line 430 handler_t plugins_call_init(server *srv) {
|
/* fill slots */ |
/* fill slots */ |
|
|
srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps)); |
srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps)); |
|
force_assert(NULL != srv->plugin_slots); |
|
|
for (i = 0; i < srv->plugins.used; i++) { |
for (i = 0; i < srv->plugins.used; i++) { |
size_t j; |
size_t j; |
Line 381 handler_t plugins_call_init(server *srv) {
|
Line 443 handler_t plugins_call_init(server *srv) {
|
plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \ |
plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \ |
if (!slot) { \ |
if (!slot) { \ |
slot = calloc(srv->plugins.used, sizeof(*slot));\ |
slot = calloc(srv->plugins.used, sizeof(*slot));\ |
|
force_assert(NULL != slot); \ |
((plugin ***)(srv->plugin_slots))[x] = slot; \ |
((plugin ***)(srv->plugin_slots))[x] = slot; \ |
} \ |
} \ |
for (j = 0; j < srv->plugins.used; j++) { \ |
for (j = 0; j < srv->plugins.used; j++) { \ |
Line 399 handler_t plugins_call_init(server *srv) {
|
Line 462 handler_t plugins_call_init(server *srv) {
|
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist); |
|
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset); |
PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset); |