Started working on mod_welcome which will replace the built-in file_motd and file_rules configuration options.

This commit is contained in:
Jan Vidar Krey 2011-12-21 14:31:29 +01:00
parent b24d4b85cd
commit 88dd1341d2
2 changed files with 315 additions and 6 deletions

View File

@ -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)

301
src/plugins/mod_welcome.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#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 <syslog.h>
#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(&timestamp);
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;
}