Added mod_chat_history_sqlite and mod_chat_is_privileged.
Use file=/path/to/db to specify the database file where chat history should be stored. Other config variables are the same as those for mod_chat_history. Code merged adapted and merged from Mimicmod's repository: https://github.com/mimicmod/uhub.git
This commit is contained in:
parent
cd5c4ee622
commit
5672ba14e3
2
AUTHORS
2
AUTHORS
|
@ -4,7 +4,7 @@ Authors of uhub
|
||||||
Jan Vidar Krey, Design and implementation
|
Jan Vidar Krey, Design and implementation
|
||||||
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
||||||
FleetCommand, Hub topic plugin code
|
FleetCommand, Hub topic plugin code
|
||||||
MiMic, Implemented user commands
|
MiMic, Implemented user commands, and plugins
|
||||||
Boris Pek (tehnick), Debian/Ubuntu packaging
|
Boris Pek (tehnick), Debian/Ubuntu packaging
|
||||||
Tillmann Karras (Tilka), Misc. bug fixes
|
Tillmann Karras (Tilka), Misc. bug fixes
|
||||||
Yoran Heling (Yorhel), TLS/SSL handshake detection bugfixes
|
Yoran Heling (Yorhel), TLS/SSL handshake detection bugfixes
|
||||||
|
|
|
@ -92,7 +92,9 @@ add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c)
|
||||||
add_library(mod_logging MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_logging.c ${PROJECT_SOURCE_DIR}/adc/sid.c)
|
add_library(mod_logging MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_logging.c ${PROJECT_SOURCE_DIR}/adc/sid.c)
|
||||||
add_library(mod_auth_simple MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_simple.c )
|
add_library(mod_auth_simple MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_simple.c )
|
||||||
add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c )
|
add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c )
|
||||||
|
add_library(mod_chat_history_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history_sqlite.c )
|
||||||
add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c)
|
add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c)
|
||||||
|
add_library(mod_chat_is_privileged MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_is_privileged.c)
|
||||||
add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c)
|
add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c)
|
||||||
add_library(mod_no_guest_downloads MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_no_guest_downloads.c)
|
add_library(mod_no_guest_downloads MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_no_guest_downloads.c)
|
||||||
add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c)
|
add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c)
|
||||||
|
@ -111,7 +113,9 @@ set_target_properties(
|
||||||
mod_auth_simple
|
mod_auth_simple
|
||||||
mod_auth_sqlite
|
mod_auth_sqlite
|
||||||
mod_chat_history
|
mod_chat_history
|
||||||
|
mod_chat_history_sqlite
|
||||||
mod_chat_only
|
mod_chat_only
|
||||||
|
mod_chat_is_privileged
|
||||||
mod_no_guest_downloads
|
mod_no_guest_downloads
|
||||||
mod_topic
|
mod_topic
|
||||||
PROPERTIES PREFIX "")
|
PROPERTIES PREFIX "")
|
||||||
|
@ -124,8 +128,10 @@ target_link_libraries(mod_welcome utils)
|
||||||
target_link_libraries(mod_auth_simple utils)
|
target_link_libraries(mod_auth_simple utils)
|
||||||
target_link_libraries(mod_auth_sqlite ${SQLITE3_LIBRARIES} utils)
|
target_link_libraries(mod_auth_sqlite ${SQLITE3_LIBRARIES} utils)
|
||||||
target_link_libraries(mod_chat_history utils)
|
target_link_libraries(mod_chat_history utils)
|
||||||
|
target_link_libraries(mod_chat_history_sqlite ${SQLITE3_LIBRARIES} utils)
|
||||||
target_link_libraries(mod_no_guest_downloads utils)
|
target_link_libraries(mod_no_guest_downloads utils)
|
||||||
target_link_libraries(mod_chat_only utils)
|
target_link_libraries(mod_chat_only utils)
|
||||||
|
target_link_libraries(mod_chat_is_privileged utils)
|
||||||
target_link_libraries(mod_logging utils)
|
target_link_libraries(mod_logging utils)
|
||||||
target_link_libraries(mod_topic utils)
|
target_link_libraries(mod_topic utils)
|
||||||
target_link_libraries(utils network)
|
target_link_libraries(utils network)
|
||||||
|
@ -217,7 +223,7 @@ endif()
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
install( TARGETS uhub uhub-passwd RUNTIME DESTINATION bin )
|
install( TARGETS uhub uhub-passwd RUNTIME DESTINATION bin )
|
||||||
install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_only mod_topic mod_no_guest_downloads DESTINATION /usr/lib/uhub/ OPTIONAL )
|
install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_history_sqlite mod_chat_only mod_chat_is_privileged mod_topic mod_no_guest_downloads DESTINATION /usr/lib/uhub/ OPTIONAL )
|
||||||
install( FILES ${CMAKE_SOURCE_DIR}/doc/uhub.conf ${CMAKE_SOURCE_DIR}/doc/plugins.conf ${CMAKE_SOURCE_DIR}/doc/rules.txt ${CMAKE_SOURCE_DIR}/doc/motd.txt DESTINATION /etc/uhub OPTIONAL )
|
install( FILES ${CMAKE_SOURCE_DIR}/doc/uhub.conf ${CMAKE_SOURCE_DIR}/doc/plugins.conf ${CMAKE_SOURCE_DIR}/doc/rules.txt ${CMAKE_SOURCE_DIR}/doc/motd.txt DESTINATION /etc/uhub OPTIONAL )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,347 @@
|
||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2013, 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 "plugin_api/handle.h"
|
||||||
|
#include "plugin_api/command_api.h"
|
||||||
|
#include "util/config_token.h"
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/misc.h"
|
||||||
|
#include "util/list.h"
|
||||||
|
#include "util/cbuffer.h"
|
||||||
|
|
||||||
|
#define MAX_HISTORY_SIZE 16384
|
||||||
|
|
||||||
|
struct chat_history_data
|
||||||
|
{
|
||||||
|
size_t history_max; ///<<< "the maximum number of chat messages kept in history."
|
||||||
|
size_t history_default; ///<<< "the default number of chat messages returned if no limit was provided"
|
||||||
|
size_t history_connect; ///<<< "the number of chat messages provided when users connect to the hub."
|
||||||
|
sqlite3* db; ///<<< "The chat history storage database."
|
||||||
|
struct plugin_command_handle* command_history_handle; ///<<< "A handle to the !history command."
|
||||||
|
struct plugin_command_handle* command_historycleanup_handle; ///<<< "A handle to the !historycleanup command."
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chat_history_line
|
||||||
|
{
|
||||||
|
char message[MAX_HISTORY_SIZE];
|
||||||
|
char from[MAX_NICK_LEN];
|
||||||
|
char time[20];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int null_callback(void* ptr, int argc, char **argv, char **colName) { return 0; }
|
||||||
|
|
||||||
|
static const char* sql_escape_string(const char* str)
|
||||||
|
{
|
||||||
|
static char out[1024];
|
||||||
|
size_t i = 0;
|
||||||
|
size_t n = 0;
|
||||||
|
for (; n < strlen(str); n++)
|
||||||
|
{
|
||||||
|
if (str[n] == '\'')
|
||||||
|
out[i++] = '\'';
|
||||||
|
out[i++] = str[n];
|
||||||
|
}
|
||||||
|
out[i++] = '\0';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sql_execute(struct chat_history_data* sql, int (*callback)(void* ptr, int argc, char **argv, char **colName), void* ptr, const char* sql_fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char query[1024];
|
||||||
|
char* errMsg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
va_start(args, sql_fmt);
|
||||||
|
vsnprintf(query, sizeof(query), sql_fmt, args);
|
||||||
|
|
||||||
|
rc = sqlite3_exec(sql->db, query, callback, ptr, &errMsg);
|
||||||
|
if (rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
return -rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sqlite3_changes(sql->db);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void create_tables(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
const char* table_create = "CREATE TABLE IF NOT EXISTS chat_history"
|
||||||
|
"("
|
||||||
|
"from_nick CHAR,"
|
||||||
|
"message TEXT,"
|
||||||
|
"time TIMESTAMP DEFAULT (DATETIME('NOW'))"
|
||||||
|
");";
|
||||||
|
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
sql_execute(data, null_callback, NULL, table_create);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a chat message to history.
|
||||||
|
*/
|
||||||
|
static void history_add(struct plugin_handle* plugin, struct plugin_user* from, const char* message, int flags)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
char* history_line = strdup(sql_escape_string(message));
|
||||||
|
char* history_nick = strdup(sql_escape_string(from->nick));
|
||||||
|
|
||||||
|
sql_execute(data, null_callback, NULL, "INSERT INTO chat_history (from_nick, message) VALUES('%s', '%s');DELETE FROM chat_history WHERE time <= (SELECT time FROM chat_history ORDER BY time DESC LIMIT %d,1);", history_nick, history_line, data->history_max);
|
||||||
|
|
||||||
|
hub_free(history_line);
|
||||||
|
hub_free(history_nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain messages from the chat history as a linked list
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int get_messages_callback(void* ptr, int argc, char **argv, char **colName)
|
||||||
|
{
|
||||||
|
struct linked_list* messages = (struct linked_list*) ptr;
|
||||||
|
struct chat_history_line* line = hub_malloc(sizeof(struct chat_history_line));
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
memset(line, 0, sizeof(struct chat_history_line));
|
||||||
|
|
||||||
|
for (; i < argc; i++) {
|
||||||
|
if (strcmp(colName[i], "from_nick") == 0)
|
||||||
|
strncpy(line->from, argv[i], MAX_NICK_LEN);
|
||||||
|
else if (strcmp(colName[i], "message") == 0)
|
||||||
|
strncpy(line->message, argv[i], MAX_HISTORY_SIZE);
|
||||||
|
else if (strcmp(colName[i], "time") == 0)
|
||||||
|
strncpy(line->time, argv[i], 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_append(messages, line);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void user_login(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
struct cbuffer* buf = NULL;
|
||||||
|
struct linked_list* found = (struct linked_list*) list_create();
|
||||||
|
|
||||||
|
sql_execute(data, get_messages_callback, found, "SELECT * FROM chat_history ORDER BY time DESC LIMIT 0,%d;", (int) data->history_connect);
|
||||||
|
|
||||||
|
if (data->history_connect > 0 && list_size(found) > 0)
|
||||||
|
{
|
||||||
|
buf = cbuf_create(MAX_HISTORY_SIZE);
|
||||||
|
cbuf_append(buf, "Chat history:\n\n");
|
||||||
|
struct chat_history_line* history_line;
|
||||||
|
history_line = (struct chat_history_line*) list_get_last(found);
|
||||||
|
while (history_line)
|
||||||
|
{
|
||||||
|
cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message);
|
||||||
|
list_remove(found, history_line);
|
||||||
|
hub_free(history_line);
|
||||||
|
history_line = (struct chat_history_line*) list_get_last(found);
|
||||||
|
}
|
||||||
|
plugin->hub.send_message(plugin, user, cbuf_get(buf));
|
||||||
|
cbuf_destroy(buf);
|
||||||
|
}
|
||||||
|
list_clear(found, &hub_free);
|
||||||
|
list_destroy(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callback function for handling the !history command.
|
||||||
|
*/
|
||||||
|
static int command_history(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
struct cbuffer* buf = cbuf_create(MAX_HISTORY_SIZE);
|
||||||
|
struct linked_list* found = (struct linked_list*) list_create();
|
||||||
|
struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_integer);
|
||||||
|
int maxlines;
|
||||||
|
|
||||||
|
if (arg)
|
||||||
|
maxlines = arg->data.integer;
|
||||||
|
else
|
||||||
|
maxlines = data->history_default;
|
||||||
|
|
||||||
|
sql_execute(data, get_messages_callback, found, "SELECT * FROM chat_history ORDER BY time DESC LIMIT 0,%d;", maxlines);
|
||||||
|
|
||||||
|
size_t linecount = list_size(found);
|
||||||
|
|
||||||
|
if (linecount > 0)
|
||||||
|
{
|
||||||
|
cbuf_append_format(buf, "*** %s: Chat History:\n\n", cmd->prefix);
|
||||||
|
struct chat_history_line* history_line;
|
||||||
|
history_line = (struct chat_history_line*) list_get_last(found);
|
||||||
|
while (history_line)
|
||||||
|
{
|
||||||
|
cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message);
|
||||||
|
list_remove(found, history_line);
|
||||||
|
hub_free(history_line);
|
||||||
|
history_line = (struct chat_history_line*) list_get_last(found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cbuf_append_format(buf, "*** %s: No messages found.", cmd->prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin->hub.send_message(plugin, user, cbuf_get(buf));
|
||||||
|
cbuf_destroy(buf);
|
||||||
|
list_clear(found, &hub_free);
|
||||||
|
list_destroy(found);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_historycleanup(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
struct cbuffer* buf = cbuf_create(128);
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
rc = sql_execute(data, null_callback, NULL, "DELETE FROM chat_history;");
|
||||||
|
|
||||||
|
if (!rc)
|
||||||
|
cbuf_append_format(buf, "*** %s: Unable to clean chat history table.", cmd->prefix);
|
||||||
|
else
|
||||||
|
cbuf_append_format(buf, "*** %s: Cleaned chat history table.", cmd->prefix);
|
||||||
|
|
||||||
|
plugin->hub.send_message(plugin, user, cbuf_get(buf));
|
||||||
|
cbuf_destroy(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_error_message(struct plugin_handle* plugin, const char* msg)
|
||||||
|
{
|
||||||
|
plugin->error_msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct chat_history_data* parse_config(const char* line, struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) hub_malloc_zero(sizeof(struct chat_history_data));
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
char* token = cfg_token_get_first(tokens);
|
||||||
|
|
||||||
|
uhub_assert(data != NULL);
|
||||||
|
|
||||||
|
data->history_max = 200;
|
||||||
|
data->history_default = 25;
|
||||||
|
data->history_connect = 5;
|
||||||
|
|
||||||
|
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);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cfg_settings_get_key(setting), "file") == 0)
|
||||||
|
{
|
||||||
|
if (!data->db)
|
||||||
|
{
|
||||||
|
if (sqlite3_open(cfg_settings_get_value(setting), &data->db))
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
hub_free(data);
|
||||||
|
set_error_message(plugin, "Unable to open database file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "history_max") == 0)
|
||||||
|
{
|
||||||
|
data->history_max = (size_t) uhub_atoi(cfg_settings_get_value(setting));
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "history_default") == 0)
|
||||||
|
{
|
||||||
|
data->history_default = (size_t) uhub_atoi(cfg_settings_get_value(setting));
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "history_connect") == 0)
|
||||||
|
{
|
||||||
|
data->history_connect = (size_t) uhub_atoi(cfg_settings_get_value(setting));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unknown startup parameters given");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
token = cfg_token_get_next(tokens);
|
||||||
|
}
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data;
|
||||||
|
PLUGIN_INITIALIZE(plugin, "SQLite chat history plugin", "1.0", "Provide a global chat history log.");
|
||||||
|
|
||||||
|
plugin->funcs.on_user_chat_message = history_add;
|
||||||
|
plugin->funcs.on_user_login = user_login;
|
||||||
|
data = parse_config(config, plugin);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
plugin->ptr = data;
|
||||||
|
|
||||||
|
create_tables(plugin);
|
||||||
|
|
||||||
|
data->command_history_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle));
|
||||||
|
PLUGIN_COMMAND_INITIALIZE(data->command_history_handle, plugin, "history", "?N", auth_cred_guest, &command_history, "Show chat message history.");
|
||||||
|
plugin->hub.command_add(plugin, data->command_history_handle);
|
||||||
|
|
||||||
|
data->command_historycleanup_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle));
|
||||||
|
PLUGIN_COMMAND_INITIALIZE(data->command_historycleanup_handle, plugin, "historycleanup", "", auth_cred_admin, &command_historycleanup, "Clean chat message history.");
|
||||||
|
plugin->hub.command_add(plugin, data->command_historycleanup_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
sqlite3_close(data->db);
|
||||||
|
|
||||||
|
plugin->hub.command_del(plugin, data->command_history_handle);
|
||||||
|
plugin->hub.command_del(plugin, data->command_historycleanup_handle);
|
||||||
|
hub_free(data->command_history_handle);
|
||||||
|
hub_free(data->command_historycleanup_handle);
|
||||||
|
hub_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2013, 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 "plugin_api/handle.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
|
||||||
|
struct user_info
|
||||||
|
{
|
||||||
|
sid_t sid;
|
||||||
|
int warnings;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chat_restrictions_data
|
||||||
|
{
|
||||||
|
size_t num_users; // number of users tracked.
|
||||||
|
size_t max_users; // max users (hard limit max 1M users due to limitations in the SID (20 bits)).
|
||||||
|
struct user_info* users; // array of max_users
|
||||||
|
|
||||||
|
enum auth_credentials allow_privchat; // minimum credentials to allow using private chat
|
||||||
|
enum auth_credentials allow_op_contact; // minimum credentials to allow private chat to operators (including super and admins).
|
||||||
|
enum auth_credentials allow_mainchat; // minimum credentials to allow using main chat
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct chat_data* parse_config(struct plugin_handle* plugin, const char* line)
|
||||||
|
{
|
||||||
|
struct chat_data* data = (struct chat_data*) hub_malloc(sizeof(struct chat_data));
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
char* token = cfg_token_get_first(tokens);
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
data->num_users = 0;
|
||||||
|
data->max_users = 512;
|
||||||
|
data->users = hub_malloc_zero(sizeof(struct user_info) * data->max_users);
|
||||||
|
data->allow_mainchat = auth_cred_guest;
|
||||||
|
data->allow_op_contact = auth_cred_guest;
|
||||||
|
data->allow_privchat = auth_cred_guest;
|
||||||
|
|
||||||
|
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);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cfg_settings_get_key(setting), "allow_privchat") == 0)
|
||||||
|
{
|
||||||
|
if (!string_to_boolean(cfg_settings_get_value(setting), &data->allow_privchat))
|
||||||
|
data->allow_privchat = 0;
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "minimum_access") == 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unknown startup parameters given");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
token = cfg_token_get_next(tokens);
|
||||||
|
}
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct user_info* get_user_info(struct chat_data* data, sid_t sid)
|
||||||
|
{
|
||||||
|
struct user_info* u;
|
||||||
|
|
||||||
|
// resize buffer if needed.
|
||||||
|
if (sid >= data->max_users)
|
||||||
|
{
|
||||||
|
u = hub_malloc_zero(sizeof(struct user_info) * (sid + 1));
|
||||||
|
memcpy(u, data->users, data->max_users);
|
||||||
|
hub_free(data->users);
|
||||||
|
data->users = u;
|
||||||
|
data->max_users = sid;
|
||||||
|
u = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u = &data->users[sid];
|
||||||
|
|
||||||
|
// reset counters if the user was not previously known.
|
||||||
|
if (!u->sid)
|
||||||
|
{
|
||||||
|
u->sid = sid;
|
||||||
|
u->warnings = 0;
|
||||||
|
data->num_users++;
|
||||||
|
}
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
struct chat_data* data = (struct chat_data*) plugin->ptr;
|
||||||
|
/*struct user_info* info = */
|
||||||
|
get_user_info(data, user->sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_user_logout(struct plugin_handle* plugin, struct plugin_user* user, const char* reason)
|
||||||
|
{
|
||||||
|
struct chat_data* data = (struct chat_data*) plugin->ptr;
|
||||||
|
struct user_info* info = get_user_info(data, user->sid);
|
||||||
|
if (info->sid)
|
||||||
|
data->num_users--;
|
||||||
|
info->warnings = 0;
|
||||||
|
info->sid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st on_chat_msg(struct plugin_handle* plugin, struct plugin_user* from, const char* message)
|
||||||
|
{
|
||||||
|
struct chat_data* data = (struct chat_data*) plugin->ptr;
|
||||||
|
if (from->credentials >=
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st on_private_msg(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to, const char* message)
|
||||||
|
{
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
PLUGIN_INITIALIZE(plugin, "Privileged chat hub", "1.0", "Only registered users can send messages on the main chat.");
|
||||||
|
plugin->ptr = cip_initialize();
|
||||||
|
|
||||||
|
plugin->funcs.on_user_login = on_user_login;
|
||||||
|
plugin->funcs.on_user_logout = on_user_logout;
|
||||||
|
plugin->funcs.on_chat_msg = on_chat_msg;
|
||||||
|
plugin->funcs.on_private_msg = on_private_msg;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct chat_data* data = (struct chat_data*) plugin->ptr;
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
hub_free(data->users);
|
||||||
|
hub_free(data);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue