From 88dd1341d290edb3520d315649a7996c7bd4b343 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Wed, 21 Dec 2011 14:31:29 +0100 Subject: [PATCH] Started working on mod_welcome which will replace the built-in file_motd and file_rules configuration options. --- GNUmakefile | 20 ++- src/plugins/mod_welcome.c | 301 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 315 insertions(+), 6 deletions(-) create mode 100644 src/plugins/mod_welcome.c diff --git a/GNUmakefile b/GNUmakefile index b0cb5a4..90bd88f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -155,7 +155,6 @@ libuhub_SOURCES := \ src/network/connection.c \ src/network/epoll.c \ src/network/kqueue.c \ - src/network/network.c \ src/network/select.c \ src/network/timeout.c \ src/network/timer.c @@ -175,6 +174,7 @@ libutils_SOURCES := \ src/util/log.c \ src/util/memory.c \ src/util/misc.c \ + src/network/network.c \ src/util/rbtree.c \ src/util/tiger.c @@ -213,6 +213,9 @@ autotest_OBJECTS = autotest.o plugin_example_SOURCES := src/plugins/mod_example.c plugin_example_TARGET := mod_example.so +plugin_welcome_SOURCES := src/plugins/mod_welcome.c +plugin_welcome_TARGET := mod_welcome.so + plugin_logging_SOURCES := src/plugins/mod_logging.c plugin_logging_TARGET := mod_logging.so @@ -237,8 +240,9 @@ uhub-passwd_OBJECTS := $(uhub-passwd_SOURCES:.c=.o) adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o) admin_OBJECTS := $(admin_SOURCES:.c=.o) +all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET) $(plugin_auth_TARGET) $(plugin_auth_sqlite_TARGET) $(plugin_chat_history_TARGET) $(plugin_welcome_TARGET) all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(libutils_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS) -all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET) $(plugin_auth_TARGET) $(plugin_auth_sqlite_TARGET) $(plugin_chat_history_TARGET) +all_OBJECTS += $(all_plugins) uhub_BINARY=uhub$(BIN_EXT) uhub-passwd_BINARY=uhub-passwd$(BIN_EXT) @@ -246,16 +250,17 @@ adcrush_BINARY=adcrush$(BIN_EXT) admin_BINARY=uhub-admin$(BIN_EXT) autotest_BINARY=autotest/test$(BIN_EXT) -ifeq ($(USE_PLUGINS),YES) -all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET) $(plugin_auth_TARGET) $(plugin_auth_sqlite_TARGET) -all_OBJECTS += $(all_plugins) -endif .PHONY: revision.h.tmp all plugins %.o: %.c version.h revision.h $(MSG_CC) $(CC) -fPIC -c $(CFLAGS) -o $@ $< + +#%.so: %.c +# $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) + + all: $(uhub_BINARY) $(uhub-passwd_BINARY) plugins plugins: $(uhub_BINARY) $(all_plugins) @@ -275,6 +280,9 @@ $(plugin_logging_TARGET): $(plugin_logging_SOURCES) $(libutils_OBJECTS) $(libadc $(plugin_chat_history_TARGET): $(plugin_chat_history_SOURCE) $(libutils_OBJECTS) $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) +$(plugin_welcome_TARGET): $(plugin_welcome_SOURCES) $(libutils_OBJECTS) + $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) + $(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS) $(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) diff --git a/src/plugins/mod_welcome.c b/src/plugins/mod_welcome.c new file mode 100644 index 0000000..4dc8547 --- /dev/null +++ b/src/plugins/mod_welcome.c @@ -0,0 +1,301 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2011, Jan Vidar Krey + * + * 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 3 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "system.h" +#include "adc/adcconst.h" +#include "adc/sid.h" +#include "util/cbuffer.h" +#include "util/memory.h" +#include "util/ipcalc.h" +#include "plugin_api/handle.h" +#include "plugin_api/command_api.h" + +#include "util/misc.h" +#include "util/config_token.h" +#include + +#define MAX_WELCOME_SIZE 16384 + +struct welcome_data +{ + char* motd_file; + char* motd; + char* rules_file; + char* rules; + struct plugin_command_handle* cmd_motd; + struct plugin_command_handle* cmd_rules; +}; + +static int command_handler_motd(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd); +static int command_handler_rules(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd); + +static char* read_file(const char* filename) +{ + char* str; + char buf[MAX_WELCOME_SIZE]; + int fd = open(filename, O_RDONLY); + int ret; + + if (fd == -1) + return NULL; + + ret = read(fd, buf, MAX_WELCOME_SIZE); + close(fd); + + buf[ret > 0 ? ret : 0] = 0; + str = strdup(buf); + + return str; +} + +int read_motd(struct welcome_data* data) +{ + data->motd = read_file(data->motd_file); + return !!data->motd; +} + +int read_rules(struct welcome_data* data) +{ + data->rules = read_file(data->rules_file); + return !!data->rules; +} + +static void free_welcome_data(struct welcome_data* data) +{ + hub_free(data->cmd_motd); + hub_free(data->motd_file); + hub_free(data->motd); + hub_free(data->cmd_rules); + hub_free(data->rules_file); + hub_free(data->rules); + hub_free(data); +} + + +static void set_error_message(struct plugin_handle* plugin, const char* msg) +{ + plugin->error_msg = msg; +} + +static struct welcome_data* parse_config(const char* line, struct plugin_handle* plugin) +{ + struct welcome_data* data = (struct welcome_data*) hub_malloc_zero(sizeof(struct welcome_data)); + struct cfg_tokens* tokens = cfg_tokenize(line); + char* token = cfg_token_get_first(tokens); + + if (!data) + return 0; + + while (token) + { + struct cfg_settings* setting = cfg_settings_split(token); + + if (!setting) + { + set_error_message(plugin, "Unable to parse startup parameters"); + cfg_tokens_free(tokens); + free_welcome_data(data); + return 0; + } + + if (strcmp(cfg_settings_get_key(setting), "motd") == 0) + { + data->motd_file = strdup(cfg_settings_get_value(setting)); + if (!read_motd(data)) + { + set_error_message(plugin, "Unable to read motd file."); + cfg_tokens_free(tokens); + cfg_settings_free(setting); + free_welcome_data(data); + return 0; + } + + data->cmd_motd = hub_malloc_zero(sizeof(struct plugin_command_handle)); + PLUGIN_COMMAND_INITIALIZE(data->cmd_motd, (void*) data, "msg", "", auth_cred_guest, command_handler_motd, "Show the message of the day."); + } + else if (strcmp(cfg_settings_get_key(setting), "rules") == 0) + { + data->rules_file = strdup(cfg_settings_get_value(setting)); + if (!read_rules(data)) + { + set_error_message(plugin, "Unable to read rules file."); + cfg_tokens_free(tokens); + cfg_settings_free(setting); + free_welcome_data(data); + return 0; + } + + data->cmd_rules = hub_malloc_zero(sizeof(struct plugin_command_handle)); + PLUGIN_COMMAND_INITIALIZE(data->cmd_rules, (void*) data, "rule", "", auth_cred_guest, command_handler_rules, "Show the hub rules."); + } + else + { + set_error_message(plugin, "Unknown startup parameters given"); + cfg_tokens_free(tokens); + cfg_settings_free(setting); + free_welcome_data(data); + return 0; + } + + cfg_settings_free(setting); + token = cfg_token_get_next(tokens); + } + + cfg_tokens_free(tokens); + return data; +} + + +static struct cbuffer* parse_message(struct plugin_user* user, const char* msg) +{ + struct cbuffer* buf = cbuf_create(strlen(msg)); + const char* start = msg; + const char* offset = NULL; + time_t timestamp = time(NULL); + struct tm* now = localtime(×tamp); + + while ((offset = strchr(start, '%'))) + { + cbuf_append_bytes(buf, start, (offset - start)); + + offset++; + switch (offset[0]) + { + case 'n': + cbuf_append(buf, user->nick); + break; + + case 'a': + cbuf_append(buf, ip_convert_to_string(&user->addr)); + break; + + case '%': + cbuf_append(buf, "%"); + break; + + case 'H': + cbuf_append_strftime(buf, "%H", now); + break; + + case 'I': + cbuf_append_strftime(buf, "%I", now); + break; + + case 'P': + cbuf_append_strftime(buf, "%P", now); + break; + + case 'p': + cbuf_append_strftime(buf, "%p", now); + break; + + case 'M': + cbuf_append_strftime(buf, "%M", now); + break; + + case 'S': + cbuf_append_strftime(buf, "%S", now); + break; + } + + start = offset + 1; + } + + if (*start) + cbuf_append(buf, start); + + return buf; +} + +static void send_motd(struct plugin_handle* plugin, struct plugin_user* user) +{ + struct welcome_data* data = (struct welcome_data*) plugin->ptr; + struct cbuffer* buf = NULL; + if (data->motd) + { + buf = parse_message(user, data->motd); + plugin->hub.send_message(plugin, user, cbuf_get(buf)); + cbuf_destroy(buf); + } +} + +static void send_rules(struct plugin_handle* plugin, struct plugin_user* user) +{ + struct welcome_data* data = (struct welcome_data*) plugin->ptr; + struct cbuffer* buf = NULL; + if (data->rules) + { + buf = parse_message(user, data->rules); + plugin->hub.send_message(plugin, user, cbuf_get(buf)); + cbuf_destroy(buf); + } +} + +static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user) +{ + send_motd(plugin, user); +} + +static int command_handler_motd(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) +{ + send_motd(plugin, user); + return 1; +} + +static int command_handler_rules(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) +{ + send_rules(plugin, user); + return 1; +} + +int plugin_register(struct plugin_handle* plugin, const char* config) +{ + struct welcome_data* data; + PLUGIN_INITIALIZE(plugin, "Welcome plugin", "0.1", "Sends a welcome message to users when they log into the hub."); + data = parse_config(config, plugin); + + if (!data) + return -1; + + plugin->ptr = data; + plugin->funcs.on_user_login = on_user_login; + + if (data->cmd_motd) + plugin->hub.command_add(plugin, data->cmd_motd); + + if (data->cmd_rules) + plugin->hub.command_add(plugin, data->cmd_rules); + + return 0; +} + +int plugin_unregister(struct plugin_handle* plugin) +{ + struct welcome_data* data = (struct welcome_data*) plugin->ptr; + + if (data->cmd_motd) + plugin->hub.command_del(plugin, data->cmd_motd); + + if (data->cmd_rules) + plugin->hub.command_del(plugin, data->cmd_rules); + + free_welcome_data(data); + return 0; +} +