<commit_before>#include "first.h"

#include "plugin.h"
#include "base.h"
#include "array.h"
#include "log.h"

#include <string.h>
#include <stdlib.h>

array plugin_stats; /* global */

#ifdef HAVE_VALGRIND_VALGRIND_H
# include <valgrind/valgrind.h>
#endif

#if !defined(__WIN32) && !defined(LIGHTTPD_STATIC)
# include <dlfcn.h>
#endif
/*
 *
 * if you change this enum to add a new callback, be sure
 * - that PLUGIN_FUNC_SIZEOF is the last entry
 * - that you add:
 *   1. PLUGIN_CALL_... as callback-dispatcher
 *   2. count and assignment in plugins_call_init()
 *
 */

typedef enum {
	PLUGIN_FUNC_HANDLE_URI_CLEAN,
	PLUGIN_FUNC_HANDLE_DOCROOT,
	PLUGIN_FUNC_HANDLE_PHYSICAL,
	PLUGIN_FUNC_HANDLE_SUBREQUEST_START,
	/* PLUGIN_FUNC_HANDLE_SUBREQUEST, *//* max one handler_module per req */
	PLUGIN_FUNC_HANDLE_RESPONSE_START,
	PLUGIN_FUNC_HANDLE_REQUEST_DONE,
	PLUGIN_FUNC_HANDLE_REQUEST_RESET,
	PLUGIN_FUNC_HANDLE_REQUEST_ENV,
	PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT,
	PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR,
	PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
	PLUGIN_FUNC_HANDLE_TRIGGER,
	PLUGIN_FUNC_HANDLE_WAITPID,
	PLUGIN_FUNC_HANDLE_SIGHUP,
	/* PLUGIN_FUNC_INIT, *//* handled here in plugin.c */
	/* PLUGIN_FUNC_CLEANUP, *//* handled here in plugin.c */
	PLUGIN_FUNC_SET_DEFAULTS,
	PLUGIN_FUNC_WORKER_INIT,

	PLUGIN_FUNC_SIZEOF
} plugin_t;

static plugin *plugin_init(void) {
	plugin *p;

	p = calloc(1, sizeof(*p));
	force_assert(NULL != p);

	return p;
}

static void plugin_free(plugin *p) {
    if (NULL == p) return; /*(should not happen w/ current usage)*/
  #if !defined(LIGHTTPD_STATIC)
    if (p->lib) {
     #if defined(HAVE_VALGRIND_VALGRIND_H)
     /*if (!RUNNING_ON_VALGRIND) */
     #endif
      #if defined(__WIN32)
        FreeLibrary(p->lib);
      #else
        dlclose(p->lib);
      #endif
    }
  #endif

    free(p);
}

static void plugins_register(server *srv, plugin *p) {
	plugin **ps;
	if (srv->plugins.used == srv->plugins.size) {
		srv->plugins.size += 4;
		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.used++] = p;
}

/**
 *
 *
 *
 */

#if defined(LIGHTTPD_STATIC)

/* pre-declare functions, as there is no header for them */
#define PLUGIN_INIT(x)\
	int x ## _plugin_init(plugin *p);

#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) {
	for (uint32_t i = 0; i < srv->srvconf.modules->used; ++i) {
		data_string *ds = (data_string *)srv->srvconf.modules->data[i];
		char *module = ds->value.ptr;

		uint32_t j;
		for (j = 0; load_functions[j].name; ++j) {
			if (0 == strcmp(load_functions[j].name, module)) {
				plugin * const p = plugin_init();
				if ((*load_functions[j].plugin_init)(p)) {
					log_error(srv->errh, __FILE__, __LINE__, "%s plugin init failed", module);
					plugin_free(p);
					return -1;
				}
				plugins_register(srv, p);
				break;
			}
		}
		if (!load_functions[j].name) {
			log_error(srv->errh, __FILE__, __LINE__, "%s plugin not found", module);
			return -1;
		}
	}

	return 0;
}
#else /* defined(LIGHTTPD_STATIC) */
int plugins_load(server *srv) {
	buffer * const tb = srv->tmp_buf;
	plugin *p;
	int (*init)(plugin *pl);

	for (uint32_t i = 0; i < srv->srvconf.modules->used; ++i) {
		const buffer * const module = &((data_string *)srv->srvconf.modules->data[i])->value;
		buffer_copy_path_len2(tb, BUF_PTR_LEN(srv->srvconf.modules_dir),
		                          BUF_PTR_LEN(module));
#if defined(__WIN32) || defined(__CYGWIN__)
		buffer_append_string_len(tb, CONST_STR_LEN(".dll"));
#else
		buffer_append_string_len(tb, CONST_STR_LEN(".so"));
#endif

		p = plugin_init();
#ifdef __WIN32
		if (NULL == (p->lib = LoadLibrary(tb->ptr))) {
			LPVOID lpMsgBuf;
			FormatMessage(
				FORMAT_MESSAGE_ALLOCATE_BUFFER |
					FORMAT_MESSAGE_FROM_SYSTEM,
				NULL,
				GetLastError(),
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				(LPTSTR) &lpMsgBuf,
				0, NULL);

			log_error(srv->errh, __FILE__, __LINE__,
			  "LoadLibrary() failed %s %s", lpMsgBuf, tb->ptr);

			plugin_free(p);

			return -1;

		}
#else
		if (NULL == (p->lib = dlopen(tb->ptr, RTLD_NOW|RTLD_GLOBAL))) {
			log_error(srv->errh, __FILE__, __LINE__,
			  "dlopen() failed for: %s %s", tb->ptr, dlerror());

			plugin_free(p);

			return -1;
		}

#endif
		buffer_clear(tb);
		buffer_append_str2(tb, BUF_PTR_LEN(module),
                                       CONST_STR_LEN("_plugin_init"));<commit_msg>[core] make missing mod_deflate not a fatal error<commit_after>#include "first.h"

#include "plugin.h"
#include "base.h"
#include "array.h"
#include "log.h"

#include <string.h>
#include <stdlib.h>

array plugin_stats; /* global */

#ifdef HAVE_VALGRIND_VALGRIND_H
# include <valgrind/valgrind.h>
#endif

#if !defined(__WIN32) && !defined(LIGHTTPD_STATIC)
# include <dlfcn.h>
#endif
/*
 *
 * if you change this enum to add a new callback, be sure
 * - that PLUGIN_FUNC_SIZEOF is the last entry
 * - that you add:
 *   1. PLUGIN_CALL_... as callback-dispatcher
 *   2. count and assignment in plugins_call_init()
 *
 */

typedef enum {
	PLUGIN_FUNC_HANDLE_URI_CLEAN,
	PLUGIN_FUNC_HANDLE_DOCROOT,
	PLUGIN_FUNC_HANDLE_PHYSICAL,
	PLUGIN_FUNC_HANDLE_SUBREQUEST_START,
	/* PLUGIN_FUNC_HANDLE_SUBREQUEST, *//* max one handler_module per req */
	PLUGIN_FUNC_HANDLE_RESPONSE_START,
	PLUGIN_FUNC_HANDLE_REQUEST_DONE,
	PLUGIN_FUNC_HANDLE_REQUEST_RESET,
	PLUGIN_FUNC_HANDLE_REQUEST_ENV,
	PLUGIN_FUNC_HANDLE_CONNECTION_ACCEPT,
	PLUGIN_FUNC_HANDLE_CONNECTION_SHUT_WR,
	PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
	PLUGIN_FUNC_HANDLE_TRIGGER,
	PLUGIN_FUNC_HANDLE_WAITPID,
	PLUGIN_FUNC_HANDLE_SIGHUP,
	/* PLUGIN_FUNC_INIT, *//* handled here in plugin.c */
	/* PLUGIN_FUNC_CLEANUP, *//* handled here in plugin.c */
	PLUGIN_FUNC_SET_DEFAULTS,
	PLUGIN_FUNC_WORKER_INIT,

	PLUGIN_FUNC_SIZEOF
} plugin_t;

static plugin *plugin_init(void) {
	plugin *p;

	p = calloc(1, sizeof(*p));
	force_assert(NULL != p);

	return p;
}

static void plugin_free(plugin *p) {
    if (NULL == p) return; /*(should not happen w/ current usage)*/
  #if !defined(LIGHTTPD_STATIC)
    if (p->lib) {
     #if defined(HAVE_VALGRIND_VALGRIND_H)
     /*if (!RUNNING_ON_VALGRIND) */
     #endif
      #if defined(__WIN32)
        FreeLibrary(p->lib);
      #else
        dlclose(p->lib);
      #endif
    }
  #endif

    free(p);
}

static void plugins_register(server *srv, plugin *p) {
	plugin **ps;
	if (srv->plugins.used == srv->plugins.size) {
		srv->plugins.size += 4;
		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.used++] = p;
}

/**
 *
 *
 *
 */

#if defined(LIGHTTPD_STATIC)

/* pre-declare functions, as there is no header for them */
#define PLUGIN_INIT(x)\
	int x ## _plugin_init(plugin *p);

#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) {
	for (uint32_t i = 0; i < srv->srvconf.modules->used; ++i) {
		data_string *ds = (data_string *)srv->srvconf.modules->data[i];
		char *module = ds->value.ptr;

		uint32_t j;
		for (j = 0; load_functions[j].name; ++j) {
			if (0 == strcmp(load_functions[j].name, module)) {
				plugin * const p = plugin_init();
				if ((*load_functions[j].plugin_init)(p)) {
					log_error(srv->errh, __FILE__, __LINE__, "%s plugin init failed", module);
					plugin_free(p);
					return -1;
				}
				plugins_register(srv, p);
				break;
			}
		}
		if (!load_functions[j].name) {
			log_error(srv->errh, __FILE__, __LINE__, "%s plugin not found", module);
			if (srv->srvconf.compat_module_load) {
				if (buffer_eq_slen(&ds->value, CONST_STR_LEN("mod_deflate")))
					continue;
			}
			return -1;
		}
	}

	return 0;
}
#else /* defined(LIGHTTPD_STATIC) */
int plugins_load(server *srv) {
	buffer * const tb = srv->tmp_buf;
	plugin *p;
	int (*init)(plugin *pl);

	for (uint32_t i = 0; i < srv->srvconf.modules->used; ++i) {
		const buffer * const module = &((data_string *)srv->srvconf.modules->data[i])->value;
		buffer_copy_path_len2(tb, BUF_PTR_LEN(srv->srvconf.modules_dir),
		                          BUF_PTR_LEN(module));
#if defined(__WIN32) || defined(__CYGWIN__)
		buffer_append_string_len(tb, CONST_STR_LEN(".dll"));
#else
		buffer_append_string_len(tb, CONST_STR_LEN(".so"));
#endif

		p = plugin_init();
#ifdef __WIN32
		if (NULL == (p->lib = LoadLibrary(tb->ptr))) {
			LPVOID lpMsgBuf;
			FormatMessage(
				FORMAT_MESSAGE_ALLOCATE_BUFFER |
					FORMAT_MESSAGE_FROM_SYSTEM,
				NULL,
				GetLastError(),
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				(LPTSTR) &lpMsgBuf,
				0, NULL);

			log_error(srv->errh, __FILE__, __LINE__,
			  "LoadLibrary() failed %s %s", lpMsgBuf, tb->ptr);

			plugin_free(p);

			if (srv->srvconf.compat_module_load) {
				if (buffer_eq_slen(module, CONST_STR_LEN("mod_deflate")))
					continue;
			}
			return -1;

		}
#else
		if (NULL == (p->lib = dlopen(tb->ptr, RTLD_NOW|RTLD_GLOBAL))) {
			log_error(srv->errh, __FILE__, __LINE__,
			  "dlopen() failed for: %s %s", tb->ptr, dlerror());

			plugin_free(p);

			if (srv->srvconf.compat_module_load) {
				if (buffer_eq_slen(module, CONST_STR_LEN("mod_deflate")))
					continue;
			}
			return -1;
		}

#endif
		buffer_clear(tb);
		buffer_append_str2(tb, BUF_PTR_LEN(module),
                                       CONST_STR_LEN("_plugin_init"));
{'fraction_non_alphanumeric': 0.14451097804391216, 'fraction_numerical': 0.005988023952095809, 'mean_word_length': 3.902641878669276, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1818039', 'n_tokens_mistral': 4245, 'n_tokens_neox': 3920, 'n_words': 764}