Compare commits

..

48 Commits

Author SHA1 Message Date
Jan Vidar Krey
9651a99d46 Updated changelog. 2012-05-29 22:57:02 +02:00
Jan Vidar Krey
571abddd98 Cleaned up code generator for config file parsing. 2012-05-23 23:37:42 +02:00
Jan Vidar Krey
9ea85ad1ac Merge pull request #5 from yorhel/master
Small rewrite of convert_to_sqlite.pl
2012-05-14 14:38:22 -07:00
Jan Vidar Krey
3ae6da4a64 Print error message in case of shutting down due to errors loading plugins. 2012-05-14 23:35:53 +02:00
Jan Vidar Krey
f3754fb4e4 Fix Windows file read discrepancy. 2012-05-14 23:33:54 +02:00
Yorhel
79ca108f48 convert_to_sqlite.pl: Update to the latest SQL schema + be more Perlish
The script behaves a little different as well, but it's more simpler
this way.
2012-05-14 19:06:11 +02:00
Jan Vidar Krey
210d5d276e Fix VS2010 project file - missing .c file. 2012-05-13 23:59:27 +02:00
Jan Vidar Krey
a6d87f95ef Merge https://github.com/Tilka/uhub 2012-05-13 23:53:56 +02:00
Tilka
274f17bce0 use "I64u" instead of PRIu64 on Windows 2012-05-11 16:45:07 +02:00
Tilka
53b3087735 remove obsolete settings in uhub.conf
motd and rules are now handled by the mod_welcome plugin.
2012-05-11 03:10:05 +02:00
Tilka
8365278cbf fix uhub_itoa() and uhub_ulltoa() 2012-05-10 23:24:42 +02:00
Tilka
eb49174ab3 marked plugin callbacks that are not called yet 2012-05-10 01:37:20 +02:00
Tilka
9e52ea7eff add on_change_nick() to struct plugin_funcs
It's not called anywhere yet.
Also reorder some typedefs, rename the ip check functions and add
struct {hub,plugin}_user parameter to on_check_ip_late(). Not sure where
to insert a call to that...
2012-05-09 23:33:03 +02:00
Tilka
05fd6bb723 minimal changes 2012-05-09 23:27:06 +02:00
Boris Pek
7b77f7dc31 Updated init script in debian package. 2012-05-08 23:40:16 +03:00
Boris Pek
685e56f4c6 Updated list of man pages in debian package. 2012-05-08 23:37:37 +03:00
Boris Pek
d19e78941a Added man page for uhub-passwd. 2012-05-08 23:29:56 +03:00
Jan Vidar Krey
c5516b5729 Merge branch 'master' of https://github.com/Tilka/uhub 2012-05-06 23:15:06 +02:00
Jan Vidar Krey
3aaabbc543 Fix issue with QUI messages being allowed through the hub 2012-05-06 23:09:02 +02:00
Tilka
ccb66ced4f don't show error on SIGTERM in select() backend 2012-05-05 01:10:24 +02:00
Tilka
dce8b97bba fix dependency of 'install' target 2012-05-03 10:13:21 +02:00
Tilka
d49127b507 changed all calls to assert() to uhub_assert() 2012-05-02 21:06:46 +02:00
Jan Vidar Krey
ccded3f642 Don't strip the U4/U6 port numbers if updated after login. 2012-05-02 20:45:31 +02:00
Jan Vidar Krey
216757a1f4 Fix compile issue with double typedefs. 2012-05-02 00:29:26 +02:00
Jan Vidar Krey
458c7fa741 Remove list assertion when removing element that is not in the list.
Breaks autotest.
2012-05-01 20:40:27 +02:00
Jan Vidar Krey
74ca5a0a33 Cleaned up command handling code, by splitting into multiple files. 2012-05-01 20:15:49 +02:00
Jan Vidar Krey
9efe4bce57 Fix bug #183 - Added proper OpenSSL license exception for the GPL. 2012-04-22 22:23:11 +02:00
Tilka
e4cf01ff1f OMG OPTIMIZED 2012-04-21 16:56:22 +02:00
Tilka
82615fc86e use dh_prep instead of dh_clean -k 2012-04-21 16:53:56 +02:00
Tilka
b72f5a407a fix double free 2012-04-21 16:51:41 +02:00
Tilka
776f7d0bff use "0" instead of "false"
otherwise compilation breaks when using a C90 compiler
2012-04-21 13:35:06 +02:00
Tilka
27ceb7ad33 fix use of uninitialized struct ip_range 2012-04-21 09:46:50 +02:00
Tilka
c5036a3ff8 fix random crashes upon !reload
A struct plugin_hub_internals was falsely casted to struct
plugin_callback_data. This caused the contained commands list pointer to point to
a struct hub_info and commands->size took the value of a pointer to a struct
net_connection. Since size is increased/decreased every time an item is
added to/removed from the list, this resulted in some funny crashes.

This fix is a little dirty as it exports some internals.
2012-04-21 09:22:06 +02:00
Tilka
832277f653 fix command syntax 2012-04-21 06:08:36 +02:00
Tilka
c525e59fa5 use arg parser in !broadcast 2012-04-21 01:56:26 +02:00
Jan Vidar Krey
781f22edab Fixed tiny memory leak on reload/shutdown. 2012-04-19 20:05:37 +02:00
Jan Vidar Krey
55030935a7 Merge https://github.com/Tilka/uhub 2012-04-19 23:17:39 +02:00
Tilka
4f0c8e0356 fix multiple optional arguments
Assuming the argument definition "?xy", it was previously not possible
to specify only x. Also, the syntax will now be shown as "[x [y]]"
instead of "[x] [y]".
2012-04-19 03:06:52 +02:00
Tilka
e925db2b98 small cleanup 2012-04-19 02:56:27 +02:00
Tilka
0cbb382b14 also clean uhub-passwd 2012-04-19 02:54:56 +02:00
Tilka
303dbadac2 ignore files generated by dpkg-buildpackage 2012-04-19 02:54:21 +02:00
Tilka
e408ae3eba automatically clean up plugin commands 2012-04-19 02:53:43 +02:00
Tilka
5b6ab7e1d2 minimal documentation fixes 2012-04-19 02:44:27 +02:00
Tilka
2298f09c0f update client software link
(adcportal.com has been terminated)
2012-04-19 02:43:59 +02:00
Tilka
ad5e5d2837 update compile howto link 2012-04-19 02:43:39 +02:00
Tilka
106574008f fix debian changelog 2012-04-19 02:43:05 +02:00
Jan Vidar Krey
1dba731cc3 Fix bug #158 - Added plugin for setting topic (hub description).
Load plugin mod_topic, and it will provide 3 new user commands:

!topic - set new topic
!cleartopic - reset the topic (use default hub description)
!showtopic - show the current topic
2012-04-19 00:33:38 +02:00
Jan Vidar Krey
df7bbc094f Command arguments handling + cleanups
Fix bug #185 - Args of !commands lost/damaged.
All string arguments were incorrectly freed after being added to the argument list for a command.
Instead this fix makes sure it is properly copied into a new string, and by doing so this requires
a new API for dealing with hub command arguments in a type safe manner, and also allows for each
argument to be cleaned up properly when the command is no longer needed.

This also fixes issues with parse errors for certain types, and optional arguments (previously it was impossible
to tell the difference for an integer with value 0 or if no integer was given).

All arguments can now be accessed through the new functions
hub_command_arg_reset() and hub_command_arg_next().

These functions are also exposed to plug-ins.

The argument type notations for 'n' has changed to mean nick (string),
and 'u' is used for a user (struct hub_user - must be online).
2012-04-18 23:03:05 +02:00
59 changed files with 1648 additions and 1017 deletions

8
.gitignore vendored
View File

@@ -7,3 +7,11 @@ uhub-admin
adcrush adcrush
uhub uhub
revision.h* revision.h*
build-stamp
debian/files
debian/uhub.debhelper.log
debian/uhub.postinst.debhelper
debian/uhub.postrm.debhelper
debian/uhub.prerm.debhelper
debian/uhub.substvars
uhub-passwd

25
COPYING.OpenSSL Normal file
View File

@@ -0,0 +1,25 @@
OpenSSL License Exception
-------------------------
Copyright (c) 2007-2012, 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 3 (GPL) as published by
the Free Software Foundation.
The full text the GPL can be found in the COPYING file.
In addition this distribution of uhub may be linked against OpenSSL
according to the terms described here:
You have permission to copy, modify, propagate, and distribute a work
formed by combining OpenSSL with uhub, or a work derivative of such a
combination, even if such copying, modification, propagation, or
distribution would otherwise violate the terms of the GPL. You must
comply with the GPL in all respects for all of the code used other than
OpenSSL.
You may include this OpenSSL exception and its grant of permissions when
you distribute uhub. Inclusion of this notice with such a distribution
constitutes a grant of such permission. If you do not wish to grant these
permissions, delete this file.

View File

@@ -1,3 +1,53 @@
0.4.0:
- Cleaned up code generator for config file parsing.
- Merge pull request #5 from yorhel/master
- Print error message in case of shutting down due to errors loading plugins.
- Fix Windows file read discrepancy.
- convert_to_sqlite.pl: Update to the latest SQL schema + be more Perlish
- Fix VS2010 project file - missing .c file.
- Merge https://github.com/Tilka/uhub
- use "I64u" instead of PRIu64 on Windows
- remove obsolete settings in uhub.conf
- fix uhub_itoa() and uhub_ulltoa()
- marked plugin callbacks that are not called yet
- add on_change_nick() to struct plugin_funcs
- minimal changes
- Updated init script in debian package.
- Updated list of man pages in debian package.
- Added man page for uhub-passwd.
- Merge branch 'master' of https://github.com/Tilka/uhub
- Fix issue with QUI messages being allowed through the hub
- don't show error on SIGTERM in select() backend
- fix dependency of 'install' target
- changed all calls to assert() to uhub_assert()
- Don't strip the U4/U6 port numbers if updated after login.
- Fix compile issue with double typedefs.
- Remove list assertion when removing element that is not in the list. Breaks autotest.
- Cleaned up command handling code, by splitting into multiple files.
- Fix bug #183 - Added proper OpenSSL license exception for the GPL.
- OMG OPTIMIZED
- use dh_prep instead of dh_clean -k
- fix double free
- use "0" instead of "false"
- fix use of uninitialized struct ip_range
- fix random crashes upon !reload
- fix command syntax
- use arg parser in !broadcast
- Fixed tiny memory leak on reload/shutdown.
- Merge https://github.com/Tilka/uhub
- fix multiple optional arguments
- small cleanup
- also clean uhub-passwd
- ignore files generated by dpkg-buildpackage
- automatically clean up plugin commands
- minimal documentation fixes
- update client software link
- update compile howto link
- fix debian changelog
- Fix bug #158 - Added plugin for setting topic (hub description).
- Command arguments handling + cleanups
0.3.2: 0.3.2:
- Fixed bugs in the kqueue network backend (OSX/BSD) - Fixed bugs in the kqueue network backend (OSX/BSD)
- Rewrote the configuration backend code. - Rewrote the configuration backend code.

View File

@@ -136,6 +136,7 @@ OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " "
# Sources # Sources
libuhub_SOURCES := \ libuhub_SOURCES := \
src/core/auth.c \ src/core/auth.c \
src/core/command_parser.c \
src/core/commands.c \ src/core/commands.c \
src/core/config.c \ src/core/config.c \
src/core/eventqueue.c \ src/core/eventqueue.c \
@@ -226,12 +227,15 @@ plugin_auth_sqlite_SOURCES := src/plugins/mod_auth_sqlite.c
plugin_auth_sqlite_TARGET := mod_auth_sqlite.so plugin_auth_sqlite_TARGET := mod_auth_sqlite.so
plugin_auth_sqlite_LIBS := -lsqlite3 plugin_auth_sqlite_LIBS := -lsqlite3
plugin_chat_history_SOURCE := src/plugins/mod_chat_history.c plugin_chat_history_SOURCES := src/plugins/mod_chat_history.c
plugin_chat_history_TARGET := mod_chat_history.so plugin_chat_history_TARGET := mod_chat_history.so
plugin_chat_only_SOURCE := src/plugins/mod_chat_only.c plugin_chat_only_SOURCES := src/plugins/mod_chat_only.c
plugin_chat_only_TARGET := mod_chat_only.so plugin_chat_only_TARGET := mod_chat_only.so
plugin_topic_SOURCES := src/plugins/mod_topic.c
plugin_topic_TARGET := mod_topic.so
# Source to objects # Source to objects
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o) libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
libutils_OBJECTS := $(libutils_SOURCES:.c=.o) libutils_OBJECTS := $(libutils_SOURCES:.c=.o)
@@ -243,8 +247,26 @@ uhub-passwd_OBJECTS := $(uhub-passwd_SOURCES:.c=.o)
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o) adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
admin_OBJECTS := $(admin_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_welcome_TARGET) $(plugin_chat_history_TARGET) $(plugin_chat_only_TARGET) all_plugins := \
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(libutils_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS) $(plugin_example_TARGET) \
$(plugin_logging_TARGET) \
$(plugin_auth_TARGET) \
$(plugin_auth_sqlite_TARGET) \
$(plugin_welcome_TARGET) \
$(plugin_chat_history_TARGET) \
$(plugin_chat_only_TARGET) \
$(plugin_topic_TARGET)
all_OBJECTS := \
$(libuhub_OBJECTS) \
$(uhub_OBJECTS) \
$(libutils_OBJECTS) \
$(adcrush_OBJECTS) \
$(autotest_OBJECTS) \
$(admin_OBJECTS) \
$(libadc_common_OBJECTS) \
$(libadc_client_OBJECTS)
all_OBJECTS += $(all_plugins) all_OBJECTS += $(all_plugins)
uhub_BINARY=uhub$(BIN_EXT) uhub_BINARY=uhub$(BIN_EXT)
@@ -280,15 +302,19 @@ $(plugin_example_TARGET): $(plugin_example_SOURCES) $(libutils_OBJECTS)
$(plugin_logging_TARGET): $(plugin_logging_SOURCES) $(libutils_OBJECTS) $(libadc_common_OBJECTS) src/network/network.o $(plugin_logging_TARGET): $(plugin_logging_SOURCES) $(libutils_OBJECTS) $(libadc_common_OBJECTS) src/network/network.o
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_chat_history_TARGET): $(plugin_chat_history_SOURCE) $(libutils_OBJECTS) $(plugin_chat_history_TARGET): $(plugin_chat_history_SOURCES) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_chat_only_TARGET): $(plugin_chat_only_SOURCE) $(libutils_OBJECTS) $(plugin_chat_only_TARGET): $(plugin_chat_only_SOURCES) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_welcome_TARGET): $(plugin_welcome_SOURCES) $(libutils_OBJECTS) $(plugin_welcome_TARGET): $(plugin_welcome_SOURCES) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_topic_TARGET): $(plugin_topic_SOURCES) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS) $(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
@@ -298,7 +324,7 @@ $(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libad
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
$(uhub-passwd_BINARY): $(uhub-passwd_OBJECTS) $(uhub-passwd_BINARY): $(uhub-passwd_OBJECTS) src/util/misc.o src/util/list.o src/util/memory.o src/util/log.o
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(uhub-passwd_LIBS) $(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(uhub-passwd_LIBS)
@@ -330,7 +356,7 @@ ifeq ($(WINDOWS),YES)
install: install:
@echo "Cannot install automatically on windows." @echo "Cannot install automatically on windows."
else else
install: $(uhub_BINARY) install: all
@echo Copying $(uhub_BINARY) to $(UHUB_PREFIX)/bin/ @echo Copying $(uhub_BINARY) to $(UHUB_PREFIX)/bin/
@cp $(uhub_BINARY) $(UHUB_PREFIX)/bin/ @cp $(uhub_BINARY) $(UHUB_PREFIX)/bin/
@cp $(uhub-passwd_BINARY) $(UHUB_PREFIX)/bin/ @cp $(uhub-passwd_BINARY) $(UHUB_PREFIX)/bin/
@@ -348,7 +374,5 @@ dist-clean:
@rm -rf $(all_OBJECTS) *~ core @rm -rf $(all_OBJECTS) *~ core
clean: clean:
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) $(all_plugins) autotest.c revision.h revision.h.tmp && \ @rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(uhub-passwd_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) $(all_plugins) autotest.c revision.h revision.h.tmp && \
echo $(MSG_CLEAN) echo $(MSG_CLEAN)

2
README
View File

@@ -4,5 +4,5 @@ For the official documentation, bugs and other information, please visit:
http://www.uhub.org/ http://www.uhub.org/
For a list of compatible ADC clients, see: For a list of compatible ADC clients, see:
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software http://en.wikipedia.org/wiki/Advanced_Direct_Connect#Client_software

View File

@@ -1,6 +1,7 @@
#include <uhub.h> #include <uhub.h>
static struct hub_info* hub = NULL; static struct hub_info* hub = NULL;
static struct hub_command* cmd = NULL;
static struct hub_user user; static struct hub_user user;
static struct command_base* cbase = NULL; static struct command_base* cbase = NULL;
static struct command_handle* c_test1 = NULL; static struct command_handle* c_test1 = NULL;
@@ -17,11 +18,13 @@ static int result = 0;
EXO_TEST(setup, { EXO_TEST(setup, {
hub = hub_malloc_zero(sizeof(struct hub_info)); hub = hub_malloc_zero(sizeof(struct hub_info));
cbase = command_initialize(hub); cbase = command_initialize(hub);
hub->commands = cbase;
return cbase && hub && uman_init(hub) == 0; return cbase && hub && uman_init(hub) == 0;
}); });
static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd) static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd)
{ {
printf("test_handler\n");
result = 1; result = 1;
return 0; return 0;
} }
@@ -35,7 +38,7 @@ static struct command_handle* create_handler(const char* prefix, const char* arg
c->cred = cred; c->cred = cred;
c->handler = test_handler; c->handler = test_handler;
c->description = "A handler added by autotest."; c->description = "A handler added by autotest.";
c->description = "exotic"; c->origin = "exotic test";
c->ptr = &c->ptr; c->ptr = &c->ptr;
return c; return c;
} }
@@ -67,7 +70,7 @@ EXO_TEST(command_create, {
ADD_TEST(c_test1, "test1", "", auth_cred_guest); ADD_TEST(c_test1, "test1", "", auth_cred_guest);
ADD_TEST(c_test2, "test2", "", auth_cred_operator); ADD_TEST(c_test2, "test2", "", auth_cred_operator);
ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest); ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest);
ADD_TEST(c_test4, "test4", "n", auth_cred_guest); ADD_TEST(c_test4, "test4", "u", auth_cred_guest);
ADD_TEST(c_test5, "test5", "i", auth_cred_guest); ADD_TEST(c_test5, "test5", "i", auth_cred_guest);
ADD_TEST(c_test6, "test6", "?c", auth_cred_guest); ADD_TEST(c_test6, "test6", "?c", auth_cred_guest);
ADD_TEST(c_test6, "test7", "C", auth_cred_guest); ADD_TEST(c_test6, "test7", "C", auth_cred_guest);
@@ -78,12 +81,36 @@ extern void command_destroy(struct hub_command* cmd);
static int verify(const char* str, enum command_parse_status expected) static int verify(const char* str, enum command_parse_status expected)
{ {
struct hub_command* cmd = command_parse(cbase, &user, str); struct hub_command* cmd = command_parse(cbase, hub, &user, str);
enum command_parse_status status = cmd->status; enum command_parse_status status = cmd->status;
command_free(cmd); command_free(cmd);
return status == expected; return status == expected;
} }
static struct hub_command_arg_data* verify_argument(struct hub_command* cmd, enum hub_command_arg_type type)
{
return hub_command_arg_next(cmd, type);
}
static int verify_arg_integer(struct hub_command* cmd, int expected)
{
struct hub_command_arg_data* data = verify_argument(cmd, type_integer);
return data->data.integer == expected;
}
static int verify_arg_user(struct hub_command* cmd, struct hub_user* expected)
{
struct hub_command_arg_data* data = verify_argument(cmd, type_user);
return data->data.user == expected;
}
static int verify_arg_cred(struct hub_command* cmd, enum auth_credentials cred)
{
struct hub_command_arg_data* data = verify_argument(cmd, type_credentials);
return data->data.credentials == cred;
}
EXO_TEST(command_access_1, { return verify("!test1", cmd_status_ok); }); EXO_TEST(command_access_1, { return verify("!test1", cmd_status_ok); });
EXO_TEST(command_access_2, { return verify("!test2", cmd_status_access_error); }); EXO_TEST(command_access_2, { return verify("!test2", cmd_status_access_error); });
EXO_TEST(command_access_3, { user.credentials = auth_cred_operator; return verify("!test2", cmd_status_ok); }); EXO_TEST(command_access_3, { user.credentials = auth_cred_operator; return verify("!test2", cmd_status_ok); });
@@ -134,7 +161,77 @@ EXO_TEST(command_parse_3, { return verify("!fail", cmd_status_not_found); });
// built-in command // built-in command
EXO_TEST(command_parse_4, { return verify("!help", cmd_status_ok); }); EXO_TEST(command_parse_4, { return verify("!help", cmd_status_ok); });
#define SETUP_COMMAND(string) \
do { \
if (cmd) command_free(cmd); \
cmd = command_parse(cbase, hub, &user, string); \
} while(0)
EXO_TEST(command_argument_integer_1, {
SETUP_COMMAND("!test3");
return verify_argument(cmd, type_integer) == NULL;
});
EXO_TEST(command_argument_integer_2, {
SETUP_COMMAND("!test3 10 42");
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_argument(cmd, type_integer) == NULL;
});
EXO_TEST(command_argument_integer_3, {
SETUP_COMMAND("!test3 10 42 6784");
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_arg_integer(cmd, 6784);
});
EXO_TEST(command_argument_user_1, {
SETUP_COMMAND("!test4 tester");
return verify_arg_user(cmd, &user) ;
});
EXO_TEST(command_argument_cid_1, {
SETUP_COMMAND("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
return verify_arg_user(cmd, &user) ;
});
EXO_TEST(command_argument_cred_1, {
SETUP_COMMAND("!test7 admin");
return verify_arg_cred(cmd, auth_cred_admin);;
});
EXO_TEST(command_argument_cred_2, {
SETUP_COMMAND("!test7 op");
return verify_arg_cred(cmd, auth_cred_operator);;
});
EXO_TEST(command_argument_cred_3, {
SETUP_COMMAND("!test7 operator");
return verify_arg_cred(cmd, auth_cred_operator);
});
EXO_TEST(command_argument_cred_4, {
SETUP_COMMAND("!test7 super");
return verify_arg_cred(cmd, auth_cred_super);
});
EXO_TEST(command_argument_cred_5, {
SETUP_COMMAND("!test7 guest");
return verify_arg_cred(cmd, auth_cred_guest);
});
EXO_TEST(command_argument_cred_6, {
SETUP_COMMAND("!test7 user");
return verify_arg_cred(cmd, auth_cred_user);
});
#undef SETUP_COMMAND
EXO_TEST(command_user_destroy, { return uman_remove(hub, &user) == 0; });
EXO_TEST(command_destroy, { EXO_TEST(command_destroy, {
command_free(cmd);
cmd = NULL;
DEL_TEST(c_test1); DEL_TEST(c_test1);
DEL_TEST(c_test2); DEL_TEST(c_test2);
DEL_TEST(c_test3); DEL_TEST(c_test3);

4
debian/changelog vendored
View File

@@ -2,13 +2,13 @@ uhub (0.3.2-1) unstable; urgency=low
* Updated upstream version. * Updated upstream version.
-- Jan Vidar Krey <janvidar@extatic.org> Mon 30 May 2010 18:00:00 +0200 -- Jan Vidar Krey <janvidar@extatic.org> Mon, 30 May 2010 18:00:00 +0200
uhub (0.3.1-1) unstable; urgency=low uhub (0.3.1-1) unstable; urgency=low
* Updated version number. * Updated version number.
-- Jan Vidar Krey <janvidar@extatic.org> Mon 04 Apr 2010 16:44:21 +0200 -- Jan Vidar Krey <janvidar@extatic.org> Mon, 04 Apr 2010 16:44:21 +0200
uhub (0.3.0-2) unstable; urgency=low uhub (0.3.0-2) unstable; urgency=low

2
debian/rules vendored
View File

@@ -24,7 +24,7 @@ binary-indep: build
binary-arch: build binary-arch: build
dh_testdir dh_testdir
dh_testroot dh_testroot
dh_clean -k dh_prep
dh_installdirs dh_installdirs
$(MAKE) install $(makeopts) $(MAKE) install $(makeopts)
dh_installdocs dh_installdocs

9
debian/uhub.init vendored
View File

@@ -5,7 +5,8 @@
# Required-Stop: $remote_fs $network # Required-Stop: $remote_fs $network
# Default-Start: 2 3 4 5 # Default-Start: 2 3 4 5
# Default-Stop: 0 1 6 # Default-Stop: 0 1 6
# Short-Description: uhub - High performance ADC p2p hub. # Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO ### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin PATH=/sbin:/bin:/usr/sbin:/usr/bin
@@ -83,8 +84,12 @@ case "$1" in
$0 start $0 start
;; ;;
status)
status_of_proc $DAEMON $NAME && exit 0 || exit $?
;;
*) *)
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2
exit 1 exit 1
;; ;;
esac esac

View File

@@ -1 +1,2 @@
doc/uhub.1 doc/uhub.1
doc/uhub-passwd.1

View File

@@ -1,13 +1,13 @@
= Architecture of uHub = = Architecture of uHub =
uHub is single threaded and handles network and timer events using the uHub is single-threaded and handles network and timer events using the
libevent library. libevent library.
For each state there is a read event (and sometimes a write event) and timeout For each state there is a read event (and sometimes a write event) and timeout
event in case an expected read (or write) event does not occur. event in case an expected read (or write) event does not occur.
== Protocol overview == == Protocol overview ==
uHub use "speak" the ADC protocol, which works in short as follows: uHub "speaks" the ADC protocol, which works in short as follows:
(C = client, S = server aka uHub). (C = client, S = server aka uHub).
C: HSUP ADBASE C: HSUP ADBASE

View File

@@ -1,7 +1,7 @@
How to compile: How to compile:
--------------- ---------------
See the official compiling howto: http://www.extatic.org/uhub/compile.html See the official compiling howto: http://www.uhub.org/compile.php
Prerequisites Prerequisites

View File

@@ -31,7 +31,7 @@ The hub should send a packet containing the token back:
'IECH {token} {host:port}', aswell as the same message via TCP. 'IECH {token} {host:port}', aswell as the same message via TCP.
If the client receives the message via UDP, it should now be able to determine the type of NAT. If the client receives the message via UDP, it should now be able to determine the type of NAT.
If the client receives the message via TCP only it knows it has a firewall blocking icomming communication. If the client receives the message via TCP only it knows it has a firewall blocking incomming communication.
If the client does not receive the message, it should assume a firewall is blocking all UDP communication, If the client does not receive the message, it should assume a firewall is blocking all UDP communication,
and resume in passive mode. and resume in passive mode.

42
doc/uhub-passwd.1 Normal file
View File

@@ -0,0 +1,42 @@
.TH UHUB-PASSWD "1" "May 2012"
.SH NAME
uhub-passwd \- small utility for manipulating passwords which are
used by uhub daemon
.SH SYNOPSIS
.B uhub-passwd
\fIfilename command \fR[...]
.SH DESCRIPTION
uHub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users
on high-end servers, or a small private hub on embedded hardware.
.SH "OPTIONS"
.TP
.BI \^create
.TP
.BI \^add " username password [credentials = user]"
.TP
.BI \^del " username"
.TP
.BI \^mod " username credentials"
.TP
.BI \^pass " username password"
.TP
.BI \^list
.SH "PARAMETERS"
.TP
.B 'filename'
is a database file
.TP
.B 'username'
is a nickname (UTF\-8, up to 64 bytes)
.TP
.B 'password'
is a password (UTF\-8, up to 64 bytes)
.TP
.B 'credentials'
is one of 'admin', 'super', 'op', 'user'
.SH AUTHOR
This program was written by Jan Vidar Krey <janvidar@extatic.org>
.SH "BUG REPORTS"
If you find a bug in uhub please report it to
.B http://bugs.extatic.org/

View File

@@ -1,6 +1,6 @@
# uhub.conf - A example configuration file. # uhub.conf - A example configuration file.
# You should normally place this file in /etc/uhub/uhub.conf # You should normally place this file in /etc/uhub/uhub.conf
# And change the file_acl and file_motd below. # and customize some of the settings below.
# #
# This file is read only to the uhub deamon, and if you # This file is read only to the uhub deamon, and if you
# make changes to it while uhub is running you can send a # make changes to it while uhub is running you can send a
@@ -38,17 +38,6 @@ hub_enabled=1
# Access control list (user database) # Access control list (user database)
file_acl=/etc/uhub/users.conf file_acl=/etc/uhub/users.conf
# This file can contain a message of the day. A welcome
# message send to any client when connecting.
# If the file does not exist, is empty, or cannot be opened
# the motd will not be sent to the clients.
# Normally this message is sent to clients when connecting.
file_motd=/etc/uhub/motd.txt
# This file can contain a rules of the hub.
# Normally this message is sent to clients when write in chat !rules
file_rules=/etc/uhub/rules.txt
# This file can contain a conf for plugin subsystem # This file can contain a conf for plugin subsystem
file_plugins = /etc/uhub/plugins.conf file_plugins = /etc/uhub/plugins.conf

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -85,6 +85,10 @@ typedef uint32_t fourcc_t;
#define ADC_CMD_DINF FOURCC('D','I','N','F') #define ADC_CMD_DINF FOURCC('D','I','N','F')
#define ADC_CMD_EINF FOURCC('E','I','N','F') #define ADC_CMD_EINF FOURCC('E','I','N','F')
#define ADC_CMD_FINF FOURCC('F','I','N','F') #define ADC_CMD_FINF FOURCC('F','I','N','F')
#define ADC_CMD_BQUI FOURCC('B','Q','U','I')
#define ADC_CMD_DQUI FOURCC('D','Q','U','I')
#define ADC_CMD_EQUI FOURCC('E','Q','U','I')
#define ADC_CMD_FQUI FOURCC('F','Q','U','I')
/* Extension messages */ /* Extension messages */
#define ADC_CMD_HCHK FOURCC('H','C','H','K') #define ADC_CMD_HCHK FOURCC('H','C','H','K')

View File

@@ -127,7 +127,7 @@ static int adc_msg_cache_append(struct adc_message* msg, const char* string, siz
memcpy(&msg->cache[msg->length], string, len); memcpy(&msg->cache[msg->length], string, len);
adc_msg_set_length(msg, msg->length + len); adc_msg_set_length(msg, msg->length + len);
assert(msg->capacity > msg->length); uhub_assert(msg->capacity > msg->length);
msg->cache[msg->length] = 0; msg->cache[msg->length] = 0;
return 1; return 1;
} }

298
src/core/command_parser.c Normal file
View File

@@ -0,0 +1,298 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, 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 "uhub.h"
static void hub_command_args_free(struct hub_command* cmd)
{
struct hub_command_arg_data* data = NULL;
if (!cmd->args)
return;
for (data = (struct hub_command_arg_data*) list_get_first(cmd->args); data; data = (struct hub_command_arg_data*) list_get_next(cmd->args))
{
switch (data->type)
{
case type_string:
hub_free(data->data.string);
break;
case type_range:
hub_free(data->data.range);
break;
default:
break;
}
}
list_clear(cmd->args, hub_free);
list_destroy(cmd->args);
cmd->args = NULL;
}
void command_free(struct hub_command* cmd)
{
if (!cmd) return;
hub_free(cmd->prefix);
hub_command_args_free(cmd);
hub_free(cmd);
}
static enum command_parse_status command_extract_arguments(struct hub_info* hub, const struct hub_user* user, struct command_handle* command, struct linked_list* tokens, struct linked_list* args)
{
int arg = 0;
int opt = 0;
int greedy = 0;
char arg_code;
char* token = NULL;
char* tmp = NULL;
size_t size = 0;
struct hub_command_arg_data* data = NULL;
enum command_parse_status status = cmd_status_ok;
// Ignore the first token since it is the prefix.
token = list_get_first(tokens);
list_remove(tokens, token);
hub_free(token);
while (status == cmd_status_ok && (arg_code = command->args[arg++]))
{
if (greedy)
{
size = 1;
for (tmp = (char*) list_get_first(tokens); tmp; tmp = (char*) list_get_next(tokens))
size += (strlen(tmp) + 1);
token = hub_malloc_zero(size);
while ((tmp = list_get_first(tokens)))
{
if (*token)
strcat(token, " ");
strcat(token, tmp);
list_remove(tokens, tmp);
hub_free(tmp);
}
}
else
{
token = list_get_first(tokens);
}
if (!token || !*token)
{
if (arg_code == '?' || opt == 1)
status = cmd_status_ok;
else
status = cmd_status_missing_args;
break;
}
switch (arg_code)
{
case '?':
opt = 1;
continue;
case '+':
greedy = 1;
continue;
case 'u':
data = hub_malloc(sizeof(*data));
data->type = type_user;
data->data.user = uman_get_user_by_nick(hub, token);
if (!data->data.user)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_nick;
}
break;
case 'i':
data = hub_malloc(sizeof(*data));
data->type = type_user;
data->data.user = uman_get_user_by_cid(hub, token);
if (!data->data.user)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_cid;
}
break;
case 'a':
data = hub_malloc(sizeof(*data));
data->type = type_address;
if (ip_convert_to_binary(token, data->data.address) == -1)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_address;
}
break;
case 'r':
data = hub_malloc(sizeof(*data));
data->type = type_range;
data->data.range = hub_malloc_zero(sizeof(struct ip_range));
if (!ip_convert_address_to_range(token, data->data.range))
{
hub_free(data->data.range);
hub_free(data);
data = NULL;
status = cmd_status_arg_address;
}
break;
case 'n':
case 'm':
case 'p':
data = hub_malloc(sizeof(*data));
data->type = type_string;
data->data.string = strdup(token);
break;
case 'c':
data = hub_malloc(sizeof(*data));
data->type = type_command;
data->data.command = command_handler_lookup(hub->commands, token);
if (!data->data.command)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_command;
}
break;
case 'C':
data = hub_malloc(sizeof(*data));
data->type = type_credentials;
if (!auth_string_to_cred(token, &data->data.credentials))
{
hub_free(data);
data = NULL;
status = cmd_status_arg_cred;
}
break;
case 'N':
data = hub_malloc(sizeof(*data));
data->type = type_integer;
if (!is_number(token, &data->data.integer))
{
hub_free(data);
data = NULL;
status = cmd_status_arg_number;
}
break;
case '\0':
if (!opt)
{
status = cmd_status_missing_args;
}
else
{
status = cmd_status_ok;
}
}
if (data)
{
list_append(args, data);
data = NULL;
}
list_remove(tokens, token);
hub_free(token);
}
hub_free(data);
return status;
}
static struct command_handle* command_get_handler(struct command_base* cbase, const char* prefix, const struct hub_user* user, struct hub_command* cmd)
{
struct command_handle* handler = NULL;
uhub_assert(cmd != NULL);
if (prefix && prefix[0] && prefix[1])
{
handler = command_handler_lookup(cbase, prefix + 1);
if (handler)
{
cmd->ptr = handler->ptr;
cmd->handler = handler->handler;
cmd->status = command_is_available(handler, user->credentials) ? cmd_status_ok : cmd_status_access_error;
}
else
{
cmd->status = cmd_status_not_found;
}
}
else
{
cmd->status = cmd_status_syntax_error;
}
return handler;
}
/**
* Parse a command and break it down into a struct hub_command.
*/
struct hub_command* command_parse(struct command_base* cbase, struct hub_info* hub, const struct hub_user* user, const char* message)
{
struct linked_list* tokens = list_create();
struct hub_command* cmd = NULL;
struct command_handle* handle = NULL;
cmd = hub_malloc_zero(sizeof(struct hub_command));
cmd->status = cmd_status_ok;
cmd->message = message;
cmd->prefix = NULL;
cmd->args = list_create();
cmd->user = user;
if (split_string(message, " ", tokens, 0) <= 0)
{
cmd->status = cmd_status_syntax_error;
goto command_parse_cleanup;
}
// Setup hub command.
cmd->prefix = strdup(((char*) list_get_first(tokens)) + 1);
// Find a matching command handler
handle = command_get_handler(cbase, list_get_first(tokens), user, cmd);
if (cmd->status != cmd_status_ok)
goto command_parse_cleanup;
// Parse arguments
cmd->status = command_extract_arguments(hub, user, handle, tokens, cmd->args);
goto command_parse_cleanup;
command_parse_cleanup:
list_clear(tokens, &hub_free);
list_destroy(tokens);
return cmd;
}

131
src/core/command_parser.h Normal file
View File

@@ -0,0 +1,131 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, 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/>.
*
*/
#ifndef HAVE_UHUB_COMMAND_PARSER_H
#define HAVE_UHUB_COMMAND_PARSER_H
struct hub_command;
struct hub_user;
struct command_base;
/**
* Parse a message as a command and return a status indicating if the command
* is valid and that the arguments are sane.
*
* @param cbase Command base pointer.
* @param user User who invoked the command.
* @param message The message that is to be interpreted as a command (including the invokation prefix '!' or '+')
*
* @return a hub_command that must be freed with command_free(). @See struct hub_command.
*/
extern struct hub_command* command_parse(struct command_base* cbase, struct hub_info* hub, const struct hub_user* user, const char* message);
/**
* Free a hub_command that was created in command_parse().
*/
extern void command_free(struct hub_command* command);
enum command_parse_status
{
cmd_status_ok, /** <<< "Everything seems to OK" */
cmd_status_not_found, /** <<< "Command was not found" */
cmd_status_access_error, /** <<< "You don't have access to this command" */
cmd_status_syntax_error, /** <<< "Not a valid command." */
cmd_status_missing_args, /** <<< "Missing some or all required arguments." */
cmd_status_arg_nick, /** <<< "A nick argument does not match an online user. ('n')" */
cmd_status_arg_cid, /** <<< "A cid argument does not match an online user. ('i')." */
cmd_status_arg_address, /** <<< "A address range argument is not valid ('a')." */
cmd_status_arg_number, /** <<< "A number argument is not valid ('N')" */
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
cmd_status_arg_command, /** <<< "A command argument is not valid ('c')" */
};
enum hub_command_arg_type
{
type_integer,
type_string,
type_user,
type_address,
type_range,
type_credentials,
type_command
};
struct hub_command_arg_data
{
enum hub_command_arg_type type;
union {
int integer;
char* string;
struct hub_user* user;
struct ip_addr_encap* address;
struct ip_range* range;
enum auth_credentials credentials;
struct command_handle* command;
} data;
};
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
/**
* This struct contains all information needed to invoke
* a command, which includes the whole message, the prefix,
* the decoded arguments (according to parameter list), and
* the user pointer (ptr) which comes from the command it was matched to.
*
* The message and prefix is generally always available, but args only
* if status == cmd_status_ok.
* Handler and ptr are NULL if status == cmd_status_not_found, or status == cmd_status_access_error.
* Ptr might also be NULL if cmd_status_ok because the command that handles it was added with a NULL ptr.
*/
struct hub_command
{
const char* message; /**<<< "The complete message." */
char* prefix; /**<<< "The prefix extracted from the message." */
struct linked_list* args; /**<<< "List of arguments of type struct hub_command_arg_data. Parsed from message." */
enum command_parse_status status; /**<<< "Status of the parsed hub_command." */
command_handler handler; /**<<< "The function handler to call in order to invoke this command." */
const struct hub_user* user; /**<<< "The user who invoked this command." */
void* ptr; /**<<< "A pointer of data which came from struct command_handler" */
};
/**
* Reset the command argument iterator and return the number of arguments
* that can be extracted from a parsed command.
*
* @param cmd the command to start iterating arguments
* @return returns the number of arguments provided for the command
*/
extern size_t hub_command_arg_reset(struct hub_command* cmd);
/**
* Obtain the current argument and place it in data and increments the iterator.
* If no argument exists, or the argument is of a different type than \param type, then 0 is returned.
*
* NOTE: when calling hub_command_arg_next the first time during a command callback it is safe to assume
* that the first argument will be extracted. Thus you don't need to call hub_command_arg_reset().
*
* @param cmd the command used for iterating arguments.
* @param type the expected type of this argument
* @return NULL if no argument is found or if the argument found does not match the expected type.
*/
extern struct hub_command_arg_data* hub_command_arg_next(struct hub_command* cmd, enum hub_command_arg_type type);
#endif /* HAVE_UHUB_COMMAND_PARSER_H */

View File

@@ -20,7 +20,6 @@
#include "uhub.h" #include "uhub.h"
#ifdef DEBUG #ifdef DEBUG
// #define CRASH_DEBUG
// #define DEBUG_UNLOAD_PLUGINS // #define DEBUG_UNLOAD_PLUGINS
#endif #endif
@@ -39,7 +38,6 @@ struct command_base
struct hub_info* hub; struct hub_info* hub;
struct linked_list* handlers; struct linked_list* handlers;
size_t prefix_length_max; size_t prefix_length_max;
struct ip_range range; // cached for parsing. Only one can be used per parameter.
}; };
struct command_base* command_initialize(struct hub_info* hub) struct command_base* command_initialize(struct hub_info* hub)
@@ -62,7 +60,7 @@ struct command_base* command_initialize(struct hub_info* hub)
void command_shutdown(struct command_base* cbase) void command_shutdown(struct command_base* cbase)
{ {
commands_builtin_remove(cbase); commands_builtin_remove(cbase);
assert(list_size(cbase->handlers) == 0); uhub_assert(list_size(cbase->handlers) == 0);
list_destroy(cbase->handlers); list_destroy(cbase->handlers);
hub_free(cbase); hub_free(cbase);
} }
@@ -88,47 +86,14 @@ int command_del(struct command_base* cbase, struct command_handle* cmd)
return 1; return 1;
} }
static int command_is_available(struct command_handle* handle, const struct hub_user* user) int command_is_available(struct command_handle* handle, enum auth_credentials credentials)
{ {
uhub_assert(handle != NULL); uhub_assert(handle != NULL);
uhub_assert(user != NULL); return handle->cred <= credentials;
return handle->cred <= user->credentials;
} }
void hub_command_args_free(struct hub_command* cmd)
{
struct hub_command_arg_data* data = NULL;
if (!cmd->args) struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix)
return;
for (data = (struct hub_command_arg_data*) list_get_first(cmd->args); data; data = (struct hub_command_arg_data*) list_get_next(cmd->args))
{
switch (data->type)
{
case type_string:
hub_free(data->data.string);
break;
default:
break;
}
}
list_clear(cmd->args, hub_free);
list_destroy(cmd->args);
cmd->args = NULL;
}
void command_free(struct hub_command* cmd)
{
if (!cmd) return;
hub_free(cmd->prefix);
hub_command_args_free(cmd);
hub_free(cmd);
}
static struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix)
{ {
struct command_handle* handler = NULL; struct command_handle* handler = NULL;
size_t prefix_len = strlen(prefix); size_t prefix_len = strlen(prefix);
@@ -145,239 +110,41 @@ static struct command_handle* command_handler_lookup(struct command_base* cbase,
} }
static enum command_parse_status command_extract_arguments(struct command_base* cbase, const struct hub_user* user, struct command_handle* command, struct linked_list* tokens, struct linked_list* args)
{
int arg = 0;
int opt = 0;
char arg_code;
char* token = NULL;
struct hub_command_arg_data* data = NULL;
enum command_parse_status status = cmd_status_ok;
// Ignore the first token since it is the prefix.
token = list_get_first(tokens);
list_remove(tokens, token);
hub_free(token);
while (status == cmd_status_ok && (arg_code = command->args[arg++]))
{
token = list_get_first(tokens);
if (!token || !*token)
{
status = (arg_code == '?' ? cmd_status_ok : cmd_status_missing_args);
break;
}
switch (arg_code)
{
case '?':
opt = 1;
continue;
case 'n':
data = hub_malloc(sizeof(*data));
data->type = type_user;
data->data.user = uman_get_user_by_nick(cbase->hub, token);
if (!data->data.user)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_nick;
}
break;
case 'i':
data = hub_malloc(sizeof(*data));
data->type = type_user;
data->data.user = uman_get_user_by_cid(cbase->hub, token);
if (!data->data.user)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_cid;
}
break;
case 'a':
data = hub_malloc(sizeof(*data));
data->type = type_address;
if (ip_convert_to_binary(token, data->data.address) == -1)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_address;
}
break;
case 'r':
data = hub_malloc(sizeof(*data));
data->type = type_range;
if (!ip_convert_address_to_range(token, data->data.range))
{
hub_free(data);
data = NULL;
status = cmd_status_arg_address;
}
break;
case 'm':
case 'p':
data = hub_malloc(sizeof(*data));
data->type = type_string;
data->data.string = strdup(token);
break;
case 'c':
data = hub_malloc(sizeof(*data));
data->type = type_command;
data->data.command = command_handler_lookup(cbase, token);
if (!data->data.command)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_command;
}
break;
case 'C':
data = hub_malloc(sizeof(*data));
data->type = type_credentials;
if (!auth_string_to_cred(token, &data->data.credentials))
{
hub_free(data);
data = NULL;
status = cmd_status_arg_cred;
}
break;
case 'N':
data->type = type_integer;
if (!is_number(token, &data->data.integer))
{
hub_free(data);
data = NULL;
return cmd_status_arg_number;
}
break;
case '\0':
if (!opt)
{
status = cmd_status_missing_args;
}
else
{
status = cmd_status_ok;
}
}
if (data)
{
list_append(args, data);
data = NULL;
}
list_remove(tokens, token);
hub_free(token);
}
hub_free(data);
return status;
}
static struct command_handle* command_get_handler(struct command_base* cbase, const char* prefix, const struct hub_user* user, struct hub_command* cmd)
{
struct command_handle* handler = NULL;
uhub_assert(cmd != NULL);
if (prefix && prefix[0] && prefix[1])
{
handler = command_handler_lookup(cbase, prefix + 1);
if (handler)
{
cmd->ptr = handler->ptr;
cmd->handler = handler->handler;
cmd->status = command_is_available(handler, user) ? cmd_status_ok : cmd_status_access_error;
}
else
{
cmd->status = cmd_status_not_found;
}
}
else
{
cmd->status = cmd_status_syntax_error;
}
return handler;
}
/**
* Parse a command and break it down into a struct hub_command.
*/
struct hub_command* command_parse(struct command_base* cbase, const struct hub_user* user, const char* message)
{
struct linked_list* tokens = list_create();
struct hub_command* cmd = NULL;
struct command_handle* handle = NULL;
cmd = hub_malloc_zero(sizeof(struct hub_command));
cmd->status = cmd_status_ok;
cmd->message = message;
cmd->prefix = NULL;
cmd->args = list_create();
cmd->user = user;
if (split_string(message, " ", tokens, 0) <= 0)
{
cmd->status = cmd_status_syntax_error;
goto command_parse_cleanup;
}
// Setup hub command.
cmd->prefix = strdup(((char*) list_get_first(tokens)) + 1);
// Find a matching command handler
handle = command_get_handler(cbase, list_get_first(tokens), user, cmd);
if (cmd->status != cmd_status_ok)
goto command_parse_cleanup;
// Parse arguments
cmd->status = command_extract_arguments(cbase, user, handle, tokens, cmd->args);
goto command_parse_cleanup;
command_parse_cleanup:
list_clear(tokens, &hub_free);
list_destroy(tokens);
return cmd;
}
void command_get_syntax(struct command_handle* handler, struct cbuffer* buf) void command_get_syntax(struct command_handle* handler, struct cbuffer* buf)
{ {
size_t n = 0; size_t n, arg_count;
int opt = 0; int opt = 0;
char arg_code, last_arg = -1;
cbuf_append_format(buf, "!%s", handler->prefix);
if (handler->args) if (handler->args)
{ {
for (n = 0; n < strlen(handler->args); n++) arg_count = strlen(handler->args);
for (n = 0; n < arg_count; n++)
{ {
if (n > 0 && !opt) cbuf_append(buf, " "); if (!strchr("?+", last_arg))
switch (handler->args[n]) cbuf_append(buf, " ");
arg_code = handler->args[n];
switch (arg_code)
{ {
case '?': cbuf_append(buf, "["); opt = 1; continue; case '?': cbuf_append(buf, "["); opt++; break;
case '+': /* ignore */ break;
case 'n': cbuf_append(buf, "<nick>"); break; case 'n': cbuf_append(buf, "<nick>"); break;
case 'u': cbuf_append(buf, "<user>"); break;
case 'i': cbuf_append(buf, "<cid>"); break; case 'i': cbuf_append(buf, "<cid>"); break;
case 'a': cbuf_append(buf, "<addr>"); break; case 'a': cbuf_append(buf, "<addr>"); break;
case 'r': cbuf_append(buf, "<addr range>"); break;
case 'm': cbuf_append(buf, "<message>"); break; case 'm': cbuf_append(buf, "<message>"); break;
case 'p': cbuf_append(buf, "<password>"); break; case 'p': cbuf_append(buf, "<password>"); break;
case 'C': cbuf_append(buf, "<credentials>"); break; case 'C': cbuf_append(buf, "<credentials>"); break;
case 'c': cbuf_append(buf, "<command>"); break; case 'c': cbuf_append(buf, "<command>"); break;
case 'N': cbuf_append(buf, "<number>"); break; case 'N': cbuf_append(buf, "<number>"); break;
default: LOG_ERROR("unknown argument code '%c'", arg_code);
} }
if (opt) last_arg = arg_code;
{ }
while (opt--)
cbuf_append(buf, "]"); cbuf_append(buf, "]");
opt = 0;
}
}
} }
} }
@@ -450,7 +217,7 @@ int command_check_args(struct hub_command* cmd, struct command_handle* handler)
int command_invoke(struct command_base* cbase, struct hub_user* user, const char* message) int command_invoke(struct command_base* cbase, struct hub_user* user, const char* message)
{ {
int ret = 0; int ret = 0;
struct hub_command* cmd = command_parse(cbase, user, message); struct hub_command* cmd = command_parse(cbase, cbase->hub, user, message);
switch (cmd->status) switch (cmd->status)
{ {
@@ -466,14 +233,11 @@ int command_invoke(struct command_base* cbase, struct hub_user* user, const char
ret = send_command_access_denied(cbase, user, cmd->prefix); ret = send_command_access_denied(cbase, user, cmd->prefix);
break; break;
case cmd_status_syntax_error:
ret = send_command_syntax_error(cbase, user);
break;
case cmd_status_missing_args: case cmd_status_missing_args:
ret = send_command_missing_arguments(cbase, user, cmd); ret = send_command_missing_arguments(cbase, user, cmd);
break; break;
case cmd_status_syntax_error:
case cmd_status_arg_nick: case cmd_status_arg_nick:
case cmd_status_arg_cid: case cmd_status_arg_cid:
case cmd_status_arg_address: case cmd_status_arg_address:
@@ -489,9 +253,28 @@ int command_invoke(struct command_base* cbase, struct hub_user* user, const char
return ret; return ret;
} }
size_t hub_command_arg_reset(struct hub_command* cmd)
{
cmd->args->iterator = NULL;
return list_size(cmd->args);
}
struct hub_command_arg_data* hub_command_arg_next(struct hub_command* cmd, enum hub_command_arg_type type)
{
struct hub_command_arg_data* ptr = (struct hub_command_arg_data*) list_get_next(cmd->args);
if (!ptr)
return NULL;
uhub_assert(ptr->type == type);
if (ptr->type != type)
return NULL;
return ptr;
}
static int command_status(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd, struct cbuffer* msg) static int command_status(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd, struct cbuffer* msg)
{ {
struct cbuffer* buf = cbuf_create(cbuf_size(msg) + strlen(cmd->prefix) + 8); struct cbuffer* buf = cbuf_create(cbuf_size(msg) + strlen(cmd->prefix) + 7);
cbuf_append_format(buf, "*** %s: %s", cmd->prefix, cbuf_get(msg)); cbuf_append_format(buf, "*** %s: %s", cmd->prefix, cbuf_get(msg));
send_message(cbase, user, buf); send_message(cbase, user, buf);
cbuf_destroy(msg); cbuf_destroy(msg);
@@ -502,16 +285,16 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc
{ {
size_t n; size_t n;
struct cbuffer* buf = cbuf_create(MAX_HELP_LINE); struct cbuffer* buf = cbuf_create(MAX_HELP_LINE);
struct hub_command_arg_data* data = list_get_first(cmd->args); struct hub_command_arg_data* data = hub_command_arg_next(cmd, type_command);
struct command_handle* command = data->data.command; struct command_handle* command;
if (!command) if (!data)
{ {
cbuf_append(buf, "Available commands:\n"); cbuf_append(buf, "Available commands:\n");
for (command = (struct command_handle*) list_get_first(cbase->handlers); command; command = (struct command_handle*) list_get_next(cbase->handlers)) for (command = (struct command_handle*) list_get_first(cbase->handlers); command; command = (struct command_handle*) list_get_next(cbase->handlers))
{ {
if (command_is_available(command, user)) if (command_is_available(command, user->credentials))
{ {
cbuf_append_format(buf, "!%s", command->prefix); cbuf_append_format(buf, "!%s", command->prefix);
for (n = strlen(command->prefix); n < cbase->prefix_length_max; n++) for (n = strlen(command->prefix); n < cbase->prefix_length_max; n++)
@@ -522,9 +305,10 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc
} }
else else
{ {
if (command_is_available(command, user)) command = data->data.command;
if (command_is_available(command, user->credentials))
{ {
cbuf_append_format(buf, "Usage: !%s ", command->prefix); cbuf_append_format(buf, "Usage: ");
command_get_syntax(command, buf); command_get_syntax(command, buf);
cbuf_append_format(buf, "\n%s\n", command->description); cbuf_append_format(buf, "\n%s\n", command->description);
} }
@@ -559,7 +343,8 @@ static int command_uptime(struct command_base* cbase, struct hub_user* user, str
static int command_kick(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_kick(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf; struct cbuffer* buf;
struct hub_user* target = list_get_first(cmd->args); struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_user);
struct hub_user* target = arg->data.user;
buf = cbuf_create(128); buf = cbuf_create(128);
if (target == user) if (target == user)
@@ -574,49 +359,6 @@ static int command_kick(struct command_base* cbase, struct hub_user* user, struc
return command_status(cbase, user, cmd, buf); return command_status(cbase, user, cmd, buf);
} }
static int command_ban(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct hub_user* target = list_get_first(cmd->args);
if (target == user)
{
cbuf_append(buf, "Cannot kick/ban yourself");
}
else
{
cbuf_append_format(buf, "Banning user \"%s\"", target->id.nick);
hub_disconnect_user(cbase->hub, target, quit_kicked);
acl_user_ban_nick(cbase->hub->acl, target->id.nick);
acl_user_ban_cid(cbase->hub->acl, target->id.cid);
}
return command_status(cbase, user, cmd, buf);
}
static int command_unban(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
return command_status(cbase, user, cmd, cbuf_create_const("Not implemented"));
}
static int command_mute(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct hub_user* target = list_get_first(cmd->args);
struct cbuffer* buf = cbuf_create(128);
if (strlen(cmd->prefix) == 4)
{
cbuf_append_format(buf, "Muted \"%s\"", target->id.nick);
user_flag_set(target, flag_muted);
}
else
{
cbuf_append_format(buf, "Unmuted \"%s\"", target->id.nick);
user_flag_unset(target, flag_muted);
}
return command_status(cbase, user, cmd, buf);
}
static int command_reload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_reload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
cbase->hub->status = hub_status_restart; cbase->hub->status = hub_status_restart;
@@ -666,20 +408,20 @@ static int command_myip(struct command_base* cbase, struct hub_user* user, struc
static int command_getip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_getip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf = cbuf_create(128); struct cbuffer* buf = cbuf_create(128);
struct hub_user* target = list_get_first(cmd->args); struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_user);
cbuf_append_format(buf, "\"%s\" has address \"%s\"", target->id.nick, user_get_address(target)); cbuf_append_format(buf, "\"%s\" has address \"%s\"", arg->data.user->id.nick, user_get_address(arg->data.user));
return command_status(cbase, user, cmd, buf); return command_status(cbase, user, cmd, buf);
} }
static int command_whoip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_whoip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf; struct cbuffer* buf;
struct ip_range* range = list_get_first(cmd->args); struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_range);
struct linked_list* users = (struct linked_list*) list_create(); struct linked_list* users = (struct linked_list*) list_create();
struct hub_user* u; struct hub_user* u;
int ret = 0; int ret = 0;
ret = uman_get_user_by_addr(cbase->hub, users, range); ret = uman_get_user_by_addr(cbase->hub, users, arg->data.range);
if (!ret) if (!ret)
{ {
list_clear(users, &null_free); list_clear(users, &null_free);
@@ -707,9 +449,9 @@ static int command_whoip(struct command_base* cbase, struct hub_user* user, stru
static int command_broadcast(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_broadcast(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
size_t offset = 11; struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_string);
size_t message_len = strlen(cmd->message + offset); char* message = arg->data.string;
char* message = adc_msg_escape(cmd->message + offset); size_t message_len = strlen(message);
char pm_flag[7] = "PM"; char pm_flag[7] = "PM";
char from_sid[5]; char from_sid[5];
size_t recipients = 0; size_t recipients = 0;
@@ -743,17 +485,17 @@ static int command_broadcast(struct command_base* cbase, struct hub_user* user,
cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : "")); cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : ""));
send_message(cbase, user, buf); send_message(cbase, user, buf);
hub_free(message);
return 0; return 0;
} }
static int command_log(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_log(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf; struct cbuffer* buf;
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_string);
struct linked_list* messages = cbase->hub->logout_info; struct linked_list* messages = cbase->hub->logout_info;
struct hub_logout_info* log; struct hub_logout_info* log;
char* search = 0; char* search = arg ? arg->data.string : "";
size_t search_len = 0; size_t search_len = strlen(search);
size_t search_hits = 0; size_t search_hits = 0;
if (!list_size(messages)) if (!list_size(messages))
@@ -764,15 +506,9 @@ static int command_log(struct command_base* cbase, struct hub_user* user, struct
buf = cbuf_create(128); buf = cbuf_create(128);
cbuf_append_format(buf, "Logged entries: " PRINTF_SIZE_T, list_size(messages)); cbuf_append_format(buf, "Logged entries: " PRINTF_SIZE_T, list_size(messages));
search = list_get_first(cmd->args);
if (search)
{
search_len = strlen(search);
}
if (search_len) if (search_len)
{ {
cbuf_append_format(buf, ", searching for \"%s\"", list_size(messages), search); cbuf_append_format(buf, ", searching for \"%s\"", search);
} }
command_status(cbase, user, cmd, buf); command_status(cbase, user, cmd, buf);
@@ -817,115 +553,6 @@ static int command_log(struct command_base* cbase, struct hub_user* user, struct
return 0; return 0;
} }
static int command_register(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct auth_info data;
struct hub_command_arg_data* args = (struct hub_command_arg_data*) list_get_first(cmd->args);
char* password = args->data.string;
strncpy(data.nickname, user->id.nick, MAX_NICK_LEN);
strncpy(data.password, password, MAX_PASS_LEN);
data.nickname[MAX_NICK_LEN] = '\0';
data.password[MAX_PASS_LEN] = '\0';
data.credentials = auth_cred_user;
if (acl_register_user(cbase->hub, &data))
{
cbuf_append_format(buf, "User \"%s\" registered.", user->id.nick);
}
else
{
cbuf_append_format(buf, "Unable to register user \"%s\".", user->id.nick);
}
return command_status(cbase, user, cmd, buf);
}
static int command_password(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct auth_info data;
struct hub_command_arg_data* args = (struct hub_command_arg_data*) list_get_first(cmd->args);
char* password = args->data.string;
strncpy(data.nickname, user->id.nick, MAX_NICK_LEN);
strncpy(data.password, password, MAX_PASS_LEN);
data.nickname[MAX_NICK_LEN] = '\0';
data.password[MAX_PASS_LEN] = '\0';
data.credentials = user->credentials;
if (acl_update_user(cbase->hub, &data))
{
cbuf_append(buf, "Password changed.");
}
else
{
cbuf_append_format(buf, "Unable to change password for user \"%s\".", user->id.nick);
}
return command_status(cbase, user, cmd, buf);
}
static int command_useradd(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct auth_info data;
char* nick = list_get_first(cmd->args);
char* pass = list_get_next(cmd->args);
char* cred = list_get_next(cmd->args);
enum auth_credentials credentials;
if (!(cred && auth_string_to_cred(cred, &credentials)))
credentials = auth_cred_user;
strncpy(data.nickname, nick, MAX_NICK_LEN);
strncpy(data.password, pass, MAX_PASS_LEN);
data.nickname[MAX_NICK_LEN] = '\0';
data.password[MAX_PASS_LEN] = '\0';
data.credentials = credentials;
if (acl_register_user(cbase->hub, &data))
cbuf_append_format(buf, "User \"%s\" registered.", nick);
else
cbuf_append_format(buf, "Unable to register user \"%s\".", nick);
return command_status(cbase, user, cmd, buf);
}
static int command_userdel(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
char* nick = list_get_first(cmd->args);
if (acl_delete_user(cbase->hub, nick))
cbuf_append_format(buf, "User \"%s\" is deleted.", nick);
else
cbuf_append_format(buf, "Unable to delete user \"%s\".", nick);
return command_status(cbase, user, cmd, buf);
}
static int command_usermod(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
return command_status(cbase, user, cmd, cbuf_create_const("Not implemented!"));
}
static int command_userinfo(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
return command_status(cbase, user, cmd, cbuf_create_const("Not implemented!"));
}
static int command_userpass(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
return command_status(cbase, user, cmd, cbuf_create_const("Not implemented!"));
}
#ifdef CRASH_DEBUG
static int command_crash(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
void (*crash)(void) = NULL;
crash();
return 0;
}
#endif
static int command_stats(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_stats(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf = cbuf_create(128); struct cbuffer* buf = cbuf_create(128);
@@ -960,32 +587,18 @@ static struct command_handle* add_builtin(struct command_base* cbase, const char
void commands_builtin_add(struct command_base* cbase) void commands_builtin_add(struct command_base* cbase)
{ {
ADD_COMMAND("ban", 3, "n", auth_cred_operator, command_ban, "Ban a user" ); ADD_COMMAND("broadcast", 9, "+m",auth_cred_operator, command_broadcast,"Send a message to all users" );
ADD_COMMAND("broadcast", 9, "m", auth_cred_operator, command_broadcast,"Send a message to all users" ); ADD_COMMAND("getip", 5, "u", auth_cred_operator, command_getip, "Show IP address for a user" );
#ifdef CRASH_DEBUG
ADD_COMMAND("crash", 5, "", auth_cred_admin, command_crash, "Crash the hub (DEBUG)." );
#endif
ADD_COMMAND("getip", 5, "n", auth_cred_operator, command_getip, "Show IP address for a user" );
ADD_COMMAND("help", 4, "?c",auth_cred_guest, command_help, "Show this help message." ); ADD_COMMAND("help", 4, "?c",auth_cred_guest, command_help, "Show this help message." );
ADD_COMMAND("kick", 4, "n", auth_cred_operator, command_kick, "Kick a user" ); ADD_COMMAND("kick", 4, "u", auth_cred_operator, command_kick, "Kick a user" );
ADD_COMMAND("log", 3, "?m",auth_cred_operator, command_log, "Display log" ); // fail ADD_COMMAND("log", 3, "?m",auth_cred_operator, command_log, "Display log" ); // fail
ADD_COMMAND("mute", 4, "n", auth_cred_operator, command_mute, "Mute user" );
ADD_COMMAND("myip", 4, "", auth_cred_guest, command_myip, "Show your own IP." ); ADD_COMMAND("myip", 4, "", auth_cred_guest, command_myip, "Show your own IP." );
ADD_COMMAND("register", 8, "p", auth_cred_guest, command_register, "Register your username." ); // fail
ADD_COMMAND("reload", 6, "", auth_cred_admin, command_reload, "Reload configuration files." ); ADD_COMMAND("reload", 6, "", auth_cred_admin, command_reload, "Reload configuration files." );
ADD_COMMAND("password", 8, "p", auth_cred_user, command_password, "Change your own password." ); // fail
ADD_COMMAND("shutdown", 8, "", auth_cred_admin, command_shutdown_hub, "Shutdown hub." ); ADD_COMMAND("shutdown", 8, "", auth_cred_admin, command_shutdown_hub, "Shutdown hub." );
ADD_COMMAND("stats", 5, "", auth_cred_super, command_stats, "Show hub statistics." ); ADD_COMMAND("stats", 5, "", auth_cred_super, command_stats, "Show hub statistics." );
ADD_COMMAND("unban", 5, "n", auth_cred_operator, command_unban, "Lift ban on a user" ); // not implemented
ADD_COMMAND("unmute", 6, "n", auth_cred_operator, command_mute, "Unmute user" );
ADD_COMMAND("uptime", 6, "", auth_cred_guest, command_uptime, "Display hub uptime info." ); ADD_COMMAND("uptime", 6, "", auth_cred_guest, command_uptime, "Display hub uptime info." );
ADD_COMMAND("useradd", 7, "np",auth_cred_operator, command_useradd, "Register a new user." ); // fail
ADD_COMMAND("userdel", 7, "n", auth_cred_operator, command_userdel, "Delete a registered user." ); // fail
ADD_COMMAND("userinfo", 8, "n", auth_cred_operator, command_userinfo, "Show registered user info." ); // fail
ADD_COMMAND("usermod", 7, "nC",auth_cred_admin, command_usermod, "Modify user credentials." ); // fail
ADD_COMMAND("userpass", 8, "np",auth_cred_operator, command_userpass, "Change password for a user." ); // fail
ADD_COMMAND("version", 7, "", auth_cred_guest, command_version, "Show hub version info." ); ADD_COMMAND("version", 7, "", auth_cred_guest, command_version, "Show hub version info." );
ADD_COMMAND("whoip", 5, "a", auth_cred_operator, command_whoip, "Show users matching IP range" ); // ok ADD_COMMAND("whoip", 5, "r", auth_cred_operator, command_whoip, "Show users matching IP range" );
#ifdef DEBUG_UNLOAD_PLUGINS #ifdef DEBUG_UNLOAD_PLUGINS
ADD_COMMAND("load", 4, "", auth_cred_admin, command_load, "Load plugins." ); ADD_COMMAND("load", 4, "", auth_cred_admin, command_load, "Load plugins." );

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,77 +24,12 @@ struct command_base;
struct command_handle; struct command_handle;
struct hub_command; struct hub_command;
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
enum command_parse_status
{
cmd_status_ok, /** <<< "Everything seems to OK" */
cmd_status_not_found, /** <<< "Command was not found" */
cmd_status_access_error, /** <<< "You don't have access to this command" */
cmd_status_syntax_error, /** <<< "Not a valid command." */
cmd_status_missing_args, /** <<< "Missing some or all required arguments." */
cmd_status_arg_nick, /** <<< "A nick argument does not match an online user. ('n')" */
cmd_status_arg_cid, /** <<< "A cid argument does not match an online user. ('i')." */
cmd_status_arg_address, /** <<< "A address range argument is not valid ('a')." */
cmd_status_arg_number, /** <<< "A number argument is not valid ('N')" */
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
cmd_status_arg_command, /** <<< "A command argument is not valid ('c')" */
};
struct hub_command_arg_data
{
enum Type {
type_integer,
type_string,
type_user,
type_address,
type_range,
type_credentials,
type_command
} type;
union {
int integer;
char* string;
struct hub_user* user;
struct ip_addr_encap* address;
struct ip_range* range;
enum auth_credentials credentials;
struct command_handle* command;
} data;
struct hub_command_arg_data* next;
};
void hub_command_args_free(struct hub_command* command);
/**
* This struct contains all information needed to invoke
* a command, which includes the whole message, the prefix,
* the decoded arguments (according to parameter list), and
* the user pointer (ptr) which comes from the command it was matched to.
*
* The message and prefix is generally always available, but args only
* if status == cmd_status_ok.
* Handler and ptr are NULL if status == cmd_status_not_found, or status == cmd_status_access_error.
* Ptr might also be NULL if cmd_status_ok because the command that handles it was added with a NULL ptr.
*/
struct hub_command
{
const char* message; /**<<< "The complete message." */
char* prefix; /**<<< "The prefix extracted from the message." */
struct linked_list* args; /**<<< "List of all parsed arguments from the message. Type depends on expectations." */
enum command_parse_status status; /**<<< "Status of the hub_command." */
command_handler handler; /**<<< "The function handler to call in order to invoke this command." */
const struct hub_user* user; /**<<< "The user who invoked this command." */
void* ptr; /**<<< "A pointer of data which came from struct command_handler" */
};
/** /**
* Argument codes are used to automatically parse arguments * Argument codes are used to automatically parse arguments
* for a a hub command. * for a a hub command.
* *
* n = nick name (must exist in hub session) * u = user (must exist in hub session, or will cause error)
* n = nick name (string)
* i = CID (must exist in hub) * i = CID (must exist in hub)
* a = (IP) address (must be a valid IPv4 or IPv6 address) * a = (IP) address (must be a valid IPv4 or IPv6 address)
* r = (IP) address range (either: IP-IP or IP/mask, both IPv4 or IPv6 work) * r = (IP) address range (either: IP-IP or IP/mask, both IPv4 or IPv6 work)
@@ -105,12 +40,17 @@ struct hub_command
* N = number (integer) * N = number (integer)
* *
* Prefix an argument with ? to make it optional. * Prefix an argument with ? to make it optional.
* NOTE; if an argument is optional then all following arguments must also be optional. * Prefix with + to make the argument greedy, which causes it to grab the rest of the line ignoring boundaries (only supported for string types).
*
* NOTE: if an argument is optional then all following arguments must also be optional.
* NOTE: You can combine optional and greedy, example: "?+m" would match "", "a", "a b c", etc.
* *
* Example: * Example:
* "nia" means "nick cid ip" * "nia" means "nick cid ip"
* "n?p" means "nick [password]" where password is optional. * "n?p" means "nick [password]" where password is optional.
* * "?N?N" means zero, one, or two integers.
* "?NN" means zero or two integers.
* "?+m" means an optional string which may contain spaces that would otherwise be split into separate arguments.
*/ */
struct command_handle struct command_handle
{ {
@@ -153,22 +93,15 @@ extern int command_del(struct command_base*, struct command_handle*);
extern int command_invoke(struct command_base*, struct hub_user* user, const char* message); extern int command_invoke(struct command_base*, struct hub_user* user, const char* message);
/** /**
* Parse a message as a command and return a status indicating if the command * Returns 1 if the command handle can be used with the given credentials, 0 otherwise.
* is valid and that the arguments are sane.
*
* @param cbase Command base pointer.
* @param user User who invoked the command.
* @param message The message that is to be interpreted as a command (including the invokation prefix '!' or '+')
*
* @return a hub_command that must be freed with command_free(). @See struct hub_command.
*/ */
extern struct hub_command* command_parse(struct command_base* cbase, const struct hub_user* user, const char* message); int command_is_available(struct command_handle* handle, enum auth_credentials credentials);
/** /**
* Free a hub_command that was created in command_parse(). * Lookup a command handle based on prefix.
* If no matching command handle is found then NULL is returned.
*/ */
extern void command_free(struct hub_command* command); struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix);
extern void commands_builtin_add(struct command_base*); extern void commands_builtin_add(struct command_base*);
extern void commands_builtin_remove(struct command_base*); extern void commands_builtin_remove(struct command_base*);

View File

@@ -1,80 +1,173 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict; use strict;
use XML::Twig; use XML::DOM;
sub write_c_header(@); sub write_c_header(@);
sub write_c_impl_defaults(@); sub write_sql_dump(@);
sub write_c_impl_apply(@);
sub write_c_impl_free(@);
sub write_c_impl_dump(@);
sub get_data($); sub get_data($);
my $dump_to_sql = 0;
# initialize parser and read the file # initialize parser and read the file
my $input = "./config.xml"; my $input = "./config.xml";
my $parser = XML::Twig->new(); my $parser = new XML::DOM::Parser;
my $tree = $parser->parsefile($input) || die "Unable to parse XML file."; my $tree = $parser->parsefile($input) || die "Unable to parse XML file.";
# Write header file # Get data
open GENHEAD, ">gen_config.h" || die "Unable to write header file"; my $nodes = $tree->getElementsByTagName("option");
print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\nstruct hub_config\n{\n"; my @options = ();
foreach my $p ($tree->root->children("option")) for (my $i = 0; $i < $nodes->getLength; $i++)
{ {
write_c_header(get_data($p)); my @data = get_data($nodes->item($i));
push @options, \@data;
} }
print GENHEAD "};\n\n";
# Write c source file write_c_header(@options);
write_sql_dump(@options) if ($dump_to_sql);
my $config_defaults = "void config_defaults(struct hub_config* config)\n{\n";
my $config_apply = "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n";
my $config_free = "void free_config(struct hub_config* config)\n{\n";
my $config_dump = "void dump_config(struct hub_config* config, int ignore_defaults)\n{\n";
foreach my $option (@options)
{
my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $check) = @$option;
my $string = ($type =~ /(string|file|message)/);
my $min = undef;
my $max = undef;
my $regexp = undef;
if (defined $check)
{
$min = $check->getAttribute("min");
$max = $check->getAttribute("max");
$regexp = $check->getAttribute("regexp");
$max = undef if ($max eq "");
$min = undef if ($min eq "");
$regexp = undef if ($regexp eq "");
}
$config_defaults .= "\tconfig->$name = ";
$config_defaults .= "hub_strdup(\"" if ($string);
$config_defaults .= $default;
$config_defaults .= "\")" if ($string);
$config_defaults .= ";\n";
$config_apply .= "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n";
if ($type eq "int")
{
$config_apply .= "\t\tmin = $min;\n" if (defined $min);
$config_apply .= "\t\tmax = $max;\n" if (defined $max);
$config_apply .= "\t\tif (!apply_integer(key, data, &config->$name, ";
if (defined $min) { $config_apply .= "&min"; } else { $config_apply .= "0"; }
$config_apply .= ", ";
if (defined $max) { $config_apply .= "&max"; } else { $config_apply .= "0"; }
$config_apply .= "))\n";
}
elsif ($type eq "boolean")
{
$config_apply .= "\t\tif (!apply_boolean(key, data, &config->$name))\n";
}
elsif ($string)
{
$config_apply .="\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n";
}
$config_apply .= "\t\t{\n" .
"\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" .
"\t\t\treturn -1;\n" .
"\t\t}\n" .
"\t\treturn 0;\n" .
"\t}\n\n";
$config_free .= "\thub_free(config->" . $name . ");\n\n" if ($string);
my $out = "%s";
my $val = "config->$name";
my $test = "config->$name != $default";
$out = "%d" if ($type eq "int");
$val = "config->$name ? \"yes\" : \"no\"" if ($type eq "boolean");
if ($string)
{
$out = "\\\"%s\\\"";
$test = "strcmp(config->$name, \"$default\") != 0";
}
$config_dump .= "\tif (!ignore_defaults || $test)\n";
$config_dump .= "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n\n";
}
$config_apply .= "\t/* Still here -- unknown directive */\n";
$config_apply .= "\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n";
$config_apply .= "\treturn -1;\n";
$config_apply .= "}\n\n";
$config_defaults .= "}\n\n";
$config_free .= "}\n\n";
$config_dump .= "}\n\n";
open GENIMPL, ">gen_config.c" || die "Unable to write source file"; open GENIMPL, ">gen_config.c" || die "Unable to write source file";
print GENIMPL "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n"; print GENIMPL "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n";
print GENIMPL $config_defaults;
print GENIMPL $config_apply;
print GENIMPL $config_free;
print GENIMPL $config_dump;
# The defaults function
print GENIMPL "void config_defaults(struct hub_config* config)\n{\n"; sub get_data($)
foreach my $p ($tree->root->children("option"))
{ {
write_c_impl_defaults(get_data($p)); my $p = shift;
my $short = "";
my $example = "";
my $description = "";
my $since = "";
$short = $p->getElementsByTagName("short")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("short")->getLength());
$since = $p->getElementsByTagName("since")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("since")->getLength());
$example = $p->getElementsByTagName("example")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("example")->getLength());
$description = $p->getElementsByTagName("description")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("description")->getLength());
my $check = $p->getElementsByTagName("check")->item(0);
my @data = (
$p->getAttribute("type"),
$p->getAttribute("name"),
$p->getAttribute("default"),
$p->getAttribute("advanced"),
$short,
$description,
$since,
$example,
$check
);
return @data;
} }
print GENIMPL "}\n\n";
# apply function
print GENIMPL "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n";
foreach my $p ($tree->root->children("option"))
{
write_c_impl_apply(get_data($p));
}
print GENIMPL "\t/* Still here -- unknown directive */\n";
print GENIMPL "\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n";
print GENIMPL "\t\treturn -1;\n";
print GENIMPL "}\n\n";
# free function (for strings)
print GENIMPL "void free_config(struct hub_config* config)\n{\n";
foreach my $p ($tree->root->children("option"))
{
write_c_impl_free(get_data($p));
}
print GENIMPL "}\n\n";
# dump function
print GENIMPL "void dump_config(struct hub_config* config, int ignore_defaults)\n{\n";
foreach my $p ($tree->root->children("option"))
{
write_c_impl_dump(get_data($p));
}
print GENIMPL "}\n\n";
# Write header file
sub write_c_header(@) sub write_c_header(@)
{ {
my @output = @_; my @data = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
open GENHEAD, ">gen_config.h" || die "Unable to write header file";
print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n";
print GENHEAD "struct hub_config\n{\n";
foreach my $option (@data)
{
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @$option;
my $string = ($type =~ /(string|file|message)/);
print GENHEAD "\t"; print GENHEAD "\t";
print GENHEAD "int " if ($type eq "int"); print GENHEAD "int " if ($type eq "int");
print GENHEAD "int " if ($type eq "boolean"); print GENHEAD "int " if ($type eq "boolean");
print GENHEAD "char*" if ($type =~ /(string|file|message)/); print GENHEAD "char*" if ($string);
print GENHEAD " " . $name . ";"; print GENHEAD " " . $name . ";";
my $comment = ""; my $comment = "";
@@ -85,7 +178,14 @@ sub write_c_header(@)
elsif (defined $short && length $short > 0) elsif (defined $short && length $short > 0)
{ {
$comment = $short; $comment = $short;
$comment .= " (default: " . $default . ")" if (defined $default); if (defined $default)
{
$comment .= " (default: ";
$comment .= "\"" if ($string);
$comment .= $default;
$comment .= "\"" if ($string);
$comment .= ")";
}
} }
if (length $comment > 0) if (length $comment > 0)
@@ -97,145 +197,74 @@ sub write_c_header(@)
} }
$comment = $pad . "/*<<< " . $comment . " */"; $comment = $pad . "/*<<< " . $comment . " */";
} }
print GENHEAD $comment . "\n"; print GENHEAD $comment . "\n";
} }
sub write_c_impl_defaults(@) print GENHEAD "};\n\n";
{
my @output = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
my $prefix = "";
my $suffix = "";
print GENIMPL "\tconfig->$name = ";
if ($type =~ /(string|file|message)/)
{
$prefix = "hub_strdup(\"";
$suffix = "\")"
}
print GENIMPL $prefix . $default . $suffix . ";\n";
} }
sub write_c_impl_apply(@)
{
my @output = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $p) = @output;
my $min; sub write_sql_dump(@)
my $max;
my $regexp;
if (defined $p)
{ {
$min = $p->att("min"); my @data = @_;
$max = $p->att("max");
$regexp = $p->att("regexp");
print "'check' is defined for option $name"; # Write SQL dump code
print ", min=$min" if (defined $min); open GENSQL, ">gen_config.sql" || die "Unable to write SQL dump";
print ", max=$max" if (defined $max); print GENSQL "START TRANSACTION;\n\n
print ", regexp=\"$regexp\"" if (defined $regexp); DROP TABLE uhub_config IF EXISTS;\n\n
print "\n"; CREATE TABLE uhub_config (
} name VARCHAR(32) UNIQUE NOT NULL,
defaultValue TINYTEXT NOT NULL,
description LONGTEXT NOT NULL,
type TINYTEXT NOT NULL,
advanced BOOLEAN,
example LONGTEXT,
since TINYTEXT
);\n\n";
print GENIMPL "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n"; foreach my $option (@data)
if ($type eq "int")
{ {
if (defined $min) my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @$option;
{
print GENIMPL "\t\tmin = $min;\n"
}
if (defined $max)
{
print GENIMPL "\t\tmax = $max;\n"
}
print GENIMPL "\t\tif (!apply_integer(key, data, &config->$name, ";
if (defined $min)
{
print GENIMPL "&min";
}
else
{
print GENIMPL "0";
}
print GENIMPL ", ";
if (defined $max)
{
print GENIMPL "&max";
}
else
{
print GENIMPL "0";
}
print GENIMPL "))\n";
}
elsif ($type eq "boolean")
{
print GENIMPL "\t\tif (!apply_boolean(key, data, &config->$name))\n";
}
elsif ($type =~ /(string|file|message)/)
{
print GENIMPL "\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n";
}
print GENIMPL "\t\t{\n" .
"\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" .
"\t\t\treturn -1;\n" .
"\t\t}\n" .
"\t\treturn 0;\n" .
"\t}\n\n";
}
sub write_c_impl_free(@)
{
my @output = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
if ($type =~ /(string|file|message)/ ) if ($type =~ /(string|file|message)/ )
{ {
print GENIMPL "\thub_free(config->" . $name . ");\n\n" $default = "\\\"$default\\\"";
}
} }
sub write_c_impl_dump(@) $desc =~ s/\"/\\\"/g;
{ $type =~ s/^int$/integer/;
my @output = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
my $out;
my $val = "config->$name";
my $test = "config->$name != $default";
if ($type eq "int") my $stmt = "INSERT INTO uhub_config VALUES(";
$stmt .= "\"$name\", ";
$stmt .= "\"$default\", ";
$stmt .= "\"$desc\", ";
$stmt .= "\"$type\", ";
if (defined $example)
{ {
$out = "%d"; my $example_str = $example;
} $example_str =~ s/\\/\\\\/g;
elsif ($type eq "boolean") $example_str =~ s/\"/\\\"/g;
{ $stmt .= "\"$example_str\", ";
$out = "%s"; } else {
$val = "config->$name ? \"yes\" : \"no\""; $stmt .= "NULL, ";
}
elsif ($type =~ /(string|file|message)/)
{
$out = "\\\"%s\\\"";
$test = "strcmp(config->$name, \"$default\") != 0";
} }
print GENIMPL "\tif (!ignore_defaults || $test)\n"; if (defined $since) {
print GENIMPL "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n\n"; $stmt .= "\"$since\", ";
} else {
$stmt .= "NULL, ";
} }
sub get_data($) if (defined $advanced) {
{ $stmt .= "\"$advanced\"";
my $p = shift; } else {
my $check = $p->first_child_matches("check"); $stmt .= "NULL";
my @data = ($p->att("type"), $p->att("name"), $p->att("default"), $p->att("advanced"), $p->children_text("short"), $p->children_text("description"), $p->children_text("since"), $p->children_text("example"), $check);
return @data;
} }
$stmt .= ");\n";
print GENSQL $stmt;
}
print GENSQL "\n\nCOMMIT;\n\n";
}

View File

@@ -13,7 +13,7 @@
<check min="1" max="65535" /> <check min="1" max="65535" />
<since>0.1.0</since> <since>0.1.0</since>
<short>Server port to bind to</short> <short>Server port to bind to</short>
<description><![CDATA[This is specifies the port number the hub should listen on.]]></description> <description><![CDATA[This specifies the port number the hub should listen on.]]></description>
</option> </option>
<option name="server_bind_addr" type="string" default="any"> <option name="server_bind_addr" type="string" default="any">
@@ -409,7 +409,7 @@
</option> </option>
<option name="tls_require" type="boolean" default="0"> <option name="tls_require" type="boolean" default="0">
<short>If SSL/TLS enabled, should it be required (default: 0)</short> <short>If SSL/TLS enabled, should it be required</short>
<description><![CDATA[ <description><![CDATA[
If TLS/SSL support is enabled it can either be optional or mandatory. If TLS/SSL support is enabled it can either be optional or mandatory.
If this option is disabled then SSL/TLS is not required to enter the hub, however it is possible to enter either with or without. If this option is disabled then SSL/TLS is not required to enter the hub, however it is possible to enter either with or without.
@@ -590,7 +590,7 @@
</option> </option>
<option name="msg_error_no_memory" type="message" default="No memory"> <option name="msg_error_no_memory" type="message" default="No memory">
<description><![CDATA[]]></description> <description><![CDATA[Hub has no more memory]]></description>
<since>0.2.0</since> <since>0.2.0</since>
</option> </option>

View File

@@ -88,7 +88,7 @@ int event_queue_process(struct event_queue* queue)
} }
list_clear(queue->q1, event_queue_cleanup_callback); list_clear(queue->q1, event_queue_cleanup_callback);
assert(list_size(queue->q1) == 0); uhub_assert(list_size(queue->q1) == 0);
/* unlock queue */ /* unlock queue */
queue->locked = 0; queue->locked = 0;

View File

@@ -102,7 +102,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "server_port")) if (!strcmp(key, "server_port"))
{ {
if (!apply_integer(key, data, &config->server_port, 0, 0)) min = 1;
max = 65535;
if (!apply_integer(key, data, &config->server_port, &min, &max))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -122,7 +124,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "server_listen_backlog")) if (!strcmp(key, "server_listen_backlog"))
{ {
if (!apply_integer(key, data, &config->server_listen_backlog, 0, 0)) min = 5;
if (!apply_integer(key, data, &config->server_listen_backlog, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -244,7 +247,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_recv_buffer")) if (!strcmp(key, "max_recv_buffer"))
{ {
if (!apply_integer(key, data, &config->max_recv_buffer, 0, 0)) min = 1024;
max = 1048576;
if (!apply_integer(key, data, &config->max_recv_buffer, &min, &max))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -254,7 +259,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_send_buffer")) if (!strcmp(key, "max_send_buffer"))
{ {
if (!apply_integer(key, data, &config->max_send_buffer, 0, 0)) min = 2048;
if (!apply_integer(key, data, &config->max_send_buffer, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -264,7 +270,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_send_buffer_soft")) if (!strcmp(key, "max_send_buffer_soft"))
{ {
if (!apply_integer(key, data, &config->max_send_buffer_soft, 0, 0)) min = 1024;
if (!apply_integer(key, data, &config->max_send_buffer_soft, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -284,7 +291,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_chat_history")) if (!strcmp(key, "max_chat_history"))
{ {
if (!apply_integer(key, data, &config->max_chat_history, 0, 0)) min = 0;
max = 250;
if (!apply_integer(key, data, &config->max_chat_history, &min, &max))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -294,7 +303,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_logout_log")) if (!strcmp(key, "max_logout_log"))
{ {
if (!apply_integer(key, data, &config->max_logout_log, 0, 0)) min = 0;
max = 2000;
if (!apply_integer(key, data, &config->max_logout_log, &min, &max))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -304,7 +315,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_hubs_user")) if (!strcmp(key, "limit_max_hubs_user"))
{ {
if (!apply_integer(key, data, &config->limit_max_hubs_user, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_max_hubs_user, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -314,7 +326,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_hubs_reg")) if (!strcmp(key, "limit_max_hubs_reg"))
{ {
if (!apply_integer(key, data, &config->limit_max_hubs_reg, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_max_hubs_reg, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -324,7 +337,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_hubs_op")) if (!strcmp(key, "limit_max_hubs_op"))
{ {
if (!apply_integer(key, data, &config->limit_max_hubs_op, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_max_hubs_op, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -334,7 +348,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_hubs")) if (!strcmp(key, "limit_max_hubs"))
{ {
if (!apply_integer(key, data, &config->limit_max_hubs, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_max_hubs, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -344,7 +359,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_min_hubs_user")) if (!strcmp(key, "limit_min_hubs_user"))
{ {
if (!apply_integer(key, data, &config->limit_min_hubs_user, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_min_hubs_user, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -354,7 +370,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_min_hubs_reg")) if (!strcmp(key, "limit_min_hubs_reg"))
{ {
if (!apply_integer(key, data, &config->limit_min_hubs_reg, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_min_hubs_reg, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -364,7 +381,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_min_hubs_op")) if (!strcmp(key, "limit_min_hubs_op"))
{ {
if (!apply_integer(key, data, &config->limit_min_hubs_op, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_min_hubs_op, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -385,7 +403,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_share")) if (!strcmp(key, "limit_max_share"))
{ {
if (!apply_integer(key, data, &config->limit_max_share, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_max_share, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -395,7 +414,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_min_slots")) if (!strcmp(key, "limit_min_slots"))
{ {
if (!apply_integer(key, data, &config->limit_min_slots, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_min_slots, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -405,7 +425,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_slots")) if (!strcmp(key, "limit_max_slots"))
{ {
if (!apply_integer(key, data, &config->limit_max_slots, 0, 0)) min = 0;
if (!apply_integer(key, data, &config->limit_max_slots, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;

View File

@@ -4,9 +4,9 @@ struct hub_config
{ {
int hub_enabled; /*<<< Is server enabled (default: 1) */ int hub_enabled; /*<<< Is server enabled (default: 1) */
int server_port; /*<<< Server port to bind to (default: 1511) */ int server_port; /*<<< Server port to bind to (default: 1511) */
char* server_bind_addr; /*<<< Server bind address (default: any) */ char* server_bind_addr; /*<<< Server bind address (default: "any") */
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */ int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: ) */ char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: "") */
int show_banner; /*<<< Show banner on connect (default: 1) */ int show_banner; /*<<< Show banner on connect (default: 1) */
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */ int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */ int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
@@ -14,9 +14,9 @@ struct hub_config
int register_self; /*<<< Allow users to register themselves on the hub. (default: 0) */ int register_self; /*<<< Allow users to register themselves on the hub. (default: 0) */
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */ int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */ int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
char* hub_name; /*<<< Name of hub (default: uhub) */ char* hub_name; /*<<< Name of hub (default: "uhub") */
char* hub_description; /*<<< Short hub description, topic or subject. (default: no description) */ char* hub_description; /*<<< Short hub description, topic or subject. (default: "no description") */
char* redirect_addr; /*<<< A common hub redirect address. (default: ) */ char* redirect_addr; /*<<< A common hub redirect address. (default: "") */
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */ int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */
int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */ int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */
int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */ int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
@@ -41,12 +41,12 @@ struct hub_config
int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */ int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */ int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */ int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) (default: 0) */ int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) */
char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: ) */ char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: "") */
char* tls_certificate; /*<<< Certificate file (default: ) */ char* tls_certificate; /*<<< Certificate file (default: "") */
char* tls_private_key; /*<<< Private key file (default: ) */ char* tls_private_key; /*<<< Private key file (default: "") */
char* file_acl; /*<<< File containing access control lists (default: ) */ char* file_acl; /*<<< File containing access control lists (default: "") */
char* file_plugins; /*<<< Plugin configuration file (default: ) */ char* file_plugins; /*<<< Plugin configuration file (default: "") */
char* msg_hub_full; /*<<< "Hub is full" */ char* msg_hub_full; /*<<< "Hub is full" */
char* msg_hub_disabled; /*<<< "Hub is disabled" */ char* msg_hub_disabled; /*<<< "Hub is disabled" */
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */ char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -76,6 +76,10 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
case ADC_CMD_DINF: case ADC_CMD_DINF:
case ADC_CMD_EINF: case ADC_CMD_EINF:
case ADC_CMD_FINF: case ADC_CMD_FINF:
case ADC_CMD_BQUI:
case ADC_CMD_DQUI:
case ADC_CMD_EQUI:
case ADC_CMD_FQUI:
/* these must never be allowed for security reasons, so we ignore them. */ /* these must never be allowed for security reasons, so we ignore them. */
CHECK_FLOOD(extras, 1); CHECK_FLOOD(extras, 1);
break; break;
@@ -524,7 +528,7 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
int status; int status;
struct hub_info* hub = (struct hub_info*) callback_data; struct hub_info* hub = (struct hub_info*) callback_data;
struct hub_user* user = (struct hub_user*) message->ptr; struct hub_user* user = (struct hub_user*) message->ptr;
assert(hub != NULL); uhub_assert(hub != NULL);
switch (message->id) switch (message->id)
{ {
@@ -901,6 +905,7 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
if (hub_plugins_load(hub) < 0) if (hub_plugins_load(hub) < 0)
{ {
LOG_FATAL("Unable to load plugins.");
hub->status = hub_status_shutdown; hub->status = hub_status_shutdown;
} }
else else

View File

@@ -52,7 +52,7 @@ void hub_recvq_destroy(struct hub_recvq* q)
size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize) size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
{ {
assert(bufsize >= q->size); uhub_assert(bufsize >= q->size);
if (q->size) if (q->size)
{ {
size_t n = q->size; size_t n = q->size;
@@ -126,7 +126,7 @@ void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
debug_msg("hub_sendq_add", msg); debug_msg("hub_sendq_add", msg);
#endif #endif
assert(msg->cache && *msg->cache); uhub_assert(msg->cache && *msg->cache);
list_append(q->queue, msg); list_append(q->queue, msg);
q->size += msg->length; q->size += msg->length;
} }
@@ -147,7 +147,7 @@ int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
int ret; int ret;
struct adc_message* msg = list_get_first(q->queue); struct adc_message* msg = list_get_first(q->queue);
if (!msg) return 0; if (!msg) return 0;
assert(msg->cache && *msg->cache); uhub_assert(msg->cache && *msg->cache);
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset); ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
if (ret > 0) if (ret > 0)

View File

@@ -226,9 +226,7 @@ static int check_network(struct hub_info* hub, struct hub_user* user, struct adc
static void strip_network(struct hub_user* user, struct adc_message* cmd) static void strip_network(struct hub_user* user, struct adc_message* cmd)
{ {
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
} }
static int nick_length_ok(const char* nick) static int nick_length_ok(const char* nick)

View File

@@ -27,10 +27,7 @@ struct plugin_callback_data
static struct plugin_callback_data* get_callback_data(struct plugin_handle* plugin) static struct plugin_callback_data* get_callback_data(struct plugin_handle* plugin)
{ {
struct plugin_callback_data* data; return get_internals(plugin)->callback_data;
uhub_assert(plugin && plugin->handle && plugin->handle->internals);
data = (struct plugin_callback_data*) plugin->handle->internals;
return data;
} }
static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
@@ -54,26 +51,6 @@ static int plugin_command_dispatch(struct command_base* cbase, struct hub_user*
return 0; return 0;
} }
struct plugin_callback_data* plugin_callback_data_create()
{
struct plugin_callback_data* data = (struct plugin_callback_data*) hub_malloc_zero(sizeof(struct plugin_callback_data));
LOG_PLUGIN("plugin_callback_data_create()");
data->commands = list_create();
return data;
}
void plugin_callback_data_destroy(struct plugin_callback_data* data)
{
LOG_PLUGIN("plugin_callback_data_destroy()");
if (data->commands)
{
uhub_assert(list_size(data->commands) == 0);
list_destroy(data->commands);
}
hub_free(data);
}
static struct hub_user* convert_user_type(struct plugin_user* user) static struct hub_user* convert_user_type(struct plugin_user* user)
{ {
struct hub_user* huser = (struct hub_user*) user; struct hub_user* huser = (struct hub_user*) user;
@@ -82,7 +59,6 @@ static struct hub_user* convert_user_type(struct plugin_user* user)
static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user* user, const char* message) static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user* user, const char* message)
{ {
// struct plugin_callback_data* data = get_callback_data(plugin);
char* buffer = adc_msg_escape(message); char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6); struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer); adc_msg_add_argument(command, buffer);
@@ -94,7 +70,6 @@ static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user*
static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message) static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message)
{ {
// struct plugin_callback_data* data = get_callback_data(plugin);
char code_str[4]; char code_str[4];
char* buffer = adc_msg_escape(message); char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_ISTA, strlen(buffer) + 10); struct adc_message* command = adc_msg_construct(ADC_CMD_ISTA, strlen(buffer) + 10);
@@ -109,7 +84,6 @@ static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user*
static int cbfunc_user_disconnect(struct plugin_handle* plugin, struct plugin_user* user) static int cbfunc_user_disconnect(struct plugin_handle* plugin, struct plugin_user* user)
{ {
// struct plugin_callback_data* data = get_callback_data(plugin);
hub_disconnect_user(plugin_get_hub(plugin), convert_user_type(user), quit_kicked); hub_disconnect_user(plugin_get_hub(plugin), convert_user_type(user), quit_kicked);
return 0; return 0;
} }
@@ -147,6 +121,69 @@ static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_comman
return 0; return 0;
} }
size_t cbfunc_command_arg_reset(struct plugin_handle* plugin, struct plugin_command* cmd)
{
// TODO: Use proper function for rewriting for plugin_command -> hub_command
return hub_command_arg_reset((struct hub_command*) cmd);
}
struct plugin_command_arg_data* cbfunc_command_arg_next(struct plugin_handle* plugin, struct plugin_command* cmd, enum plugin_command_arg_type t)
{
// TODO: Use proper function for rewriting for plugin_command -> hub_command
return (struct plugin_command_arg_data*) hub_command_arg_next((struct hub_command*) cmd, (enum hub_command_arg_type) t);
}
static char* cbfunc_get_hub_name(struct plugin_handle* plugin)
{
struct hub_info* hub = plugin_get_hub(plugin);
char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_NICK);
char* str = adc_msg_unescape(str_encoded);
hub_free(str_encoded);
return str;
}
static char* cbfunc_get_hub_description(struct plugin_handle* plugin)
{
struct hub_info* hub = plugin_get_hub(plugin);
char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION);
char* str = adc_msg_unescape(str_encoded);
hub_free(str_encoded);
return str;
}
static void cbfunc_set_hub_name(struct plugin_handle* plugin, const char* str)
{
struct hub_info* hub = plugin_get_hub(plugin);
struct adc_message* command;
char* new_str = adc_msg_escape(str ? str : hub->config->hub_name);
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_NICK, new_str);
// Broadcast hub name
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
adc_msg_add_named_argument(command, ADC_INF_FLAG_NICK, new_str);
route_to_all(hub, command);
adc_msg_free(command);
hub_free(new_str);
}
static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char* str)
{
struct hub_info* hub = plugin_get_hub(plugin);
struct adc_message* command;
char* new_str = adc_msg_escape(str ? str : hub->config->hub_description);
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, new_str);
// Broadcast hub description
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
adc_msg_add_named_argument(command, ADC_INF_FLAG_DESCRIPTION, new_str);
route_to_all(hub, command);
adc_msg_free(command);
hub_free(new_str);
}
void plugin_register_callback_functions(struct plugin_handle* handle) void plugin_register_callback_functions(struct plugin_handle* handle)
{ {
@@ -155,8 +192,37 @@ void plugin_register_callback_functions(struct plugin_handle* handle)
handle->hub.user_disconnect = cbfunc_user_disconnect; handle->hub.user_disconnect = cbfunc_user_disconnect;
handle->hub.command_add = cbfunc_command_add; handle->hub.command_add = cbfunc_command_add;
handle->hub.command_del = cbfunc_command_del; handle->hub.command_del = cbfunc_command_del;
handle->hub.command_arg_reset = cbfunc_command_arg_reset;
handle->hub.command_arg_next = cbfunc_command_arg_next;
handle->hub.get_name = cbfunc_get_hub_name;
handle->hub.set_name = cbfunc_set_hub_name;
handle->hub.get_description = cbfunc_get_hub_description;
handle->hub.set_description = cbfunc_set_hub_description;
} }
void plugin_unregister_callback_functions(struct plugin_handle* handle) void plugin_unregister_callback_functions(struct plugin_handle* handle)
{ {
} }
struct plugin_callback_data* plugin_callback_data_create()
{
struct plugin_callback_data* data = (struct plugin_callback_data*) hub_malloc_zero(sizeof(struct plugin_callback_data));
LOG_PLUGIN("plugin_callback_data_create()");
data->commands = list_create();
return data;
}
void plugin_callback_data_destroy(struct plugin_handle* plugin, struct plugin_callback_data* data)
{
LOG_PLUGIN("plugin_callback_data_destroy()");
if (data->commands)
{
// delete commands not deleted by the plugin itself:
struct plugin_command_handle* cmd;
while ( (cmd = list_get_first(data->commands)) )
cbfunc_command_del(plugin, cmd);
list_destroy(data->commands);
}
hub_free(data);
}

View File

@@ -24,7 +24,7 @@ struct plugin_handle;
struct uhub_plugin; struct uhub_plugin;
extern struct plugin_callback_data* plugin_callback_data_create(); extern struct plugin_callback_data* plugin_callback_data_create();
extern void plugin_callback_data_destroy(struct plugin_callback_data* data); extern void plugin_callback_data_destroy(struct plugin_handle* plugin, struct plugin_callback_data* data);
extern void plugin_register_callback_functions(struct plugin_handle* plugin); extern void plugin_register_callback_functions(struct plugin_handle* plugin);
extern void plugin_unregister_callback_functions(struct plugin_handle* plugin); extern void plugin_unregister_callback_functions(struct plugin_handle* plugin);

View File

@@ -82,12 +82,13 @@ static struct plugin_user* convert_user_type(struct hub_user* user)
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr) plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr)
{ {
PLUGIN_INVOKE_STATUS_1(hub, login_check_ip_early, addr); PLUGIN_INVOKE_STATUS_1(hub, on_check_ip_early, addr);
} }
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr) plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* who, struct ip_addr_encap* addr)
{ {
PLUGIN_INVOKE_STATUS_1(hub, login_check_ip_late, addr); struct plugin_user* user = convert_user_type(who);
PLUGIN_INVOKE_STATUS_2(hub, on_check_ip_late, user, addr);
} }
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr) void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr)

View File

@@ -38,7 +38,7 @@ void plugin_log_chat_message(struct hub_info* hub, struct hub_user* from, const
/* IP ban related */ /* IP ban related */
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr); plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr);
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr); plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* user, struct ip_addr_encap* addr);
/* Nickname allow/deny handling */ /* Nickname allow/deny handling */
plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick); plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick);

View File

@@ -23,17 +23,10 @@
struct plugin_callback_data; struct plugin_callback_data;
struct plugin_hub_internals struct plugin_hub_internals* get_internals(struct plugin_handle* handle)
{
struct hub_info* hub;
plugin_unregister_f unregister; /* The unregister function. */
struct plugin_callback_data* callback_data; /* callback data that is unique for the plugin */
};
static struct plugin_hub_internals* get_internals(struct plugin_handle* handle)
{ {
struct plugin_hub_internals* internals; struct plugin_hub_internals* internals;
assert(handle && handle->handle && handle->handle->internals); uhub_assert(handle && handle->handle && handle->handle->internals);
internals = (struct plugin_hub_internals*) handle->handle->internals; internals = (struct plugin_hub_internals*) handle->handle->internals;
return internals; return internals;
} }
@@ -76,7 +69,7 @@ void plugin_close(struct uhub_plugin* plugin)
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals; struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename); LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename);
plugin_callback_data_destroy(internals->callback_data); plugin_callback_data_destroy(plugin->handle, internals->callback_data);
hub_free(internals); hub_free(internals);
plugin->internals = NULL; plugin->internals = NULL;
@@ -162,8 +155,8 @@ struct plugin_handle* plugin_load(const char* filename, const char* config, stru
void plugin_unload(struct plugin_handle* plugin) void plugin_unload(struct plugin_handle* plugin)
{ {
struct plugin_hub_internals* internals = get_internals(plugin); struct plugin_hub_internals* internals = get_internals(plugin);
plugin_unregister_callback_functions(plugin);
internals->unregister(plugin); internals->unregister(plugin);
plugin_unregister_callback_functions(plugin);
plugin_close(plugin->handle); plugin_close(plugin->handle);
hub_free(plugin); hub_free(plugin);
} }

View File

@@ -32,7 +32,7 @@ struct uhub_plugin
void* handle; void* handle;
plugin_unregister_f unregister; plugin_unregister_f unregister;
char* filename; char* filename;
void* internals; // Hub internal stuff void* internals; // Hub-internal stuff (struct plugin_hub_internals)
}; };
struct uhub_plugins struct uhub_plugins
@@ -40,7 +40,7 @@ struct uhub_plugins
struct linked_list* loaded; struct linked_list* loaded;
}; };
// High level plugin loader ode // High level plugin loader code
extern struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub); extern struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub);
extern void plugin_unload(struct plugin_handle* plugin); extern void plugin_unload(struct plugin_handle* plugin);
@@ -54,7 +54,14 @@ extern void plugin_close(struct uhub_plugin*);
extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol); extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol);
// Used internally only // Used internally only
struct plugin_hub_internals
{
struct hub_info* hub;
plugin_unregister_f unregister; /* The unregister function. */
struct plugin_callback_data* callback_data; /* callback data that is unique for the plugin */
};
extern struct plugin_hub_internals* get_internals(struct plugin_handle*);
extern struct hub_info* plugin_get_hub(struct plugin_handle*); extern struct hub_info* plugin_get_hub(struct plugin_handle*);
#endif /* HAVE_UHUB_PLUGIN_LOADER_H */ #endif /* HAVE_UHUB_PLUGIN_LOADER_H */

View File

@@ -106,7 +106,7 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
if (!user->connection) if (!user->connection)
return 0; return 0;
assert(msg->cache && *msg->cache); uhub_assert(msg->cache && *msg->cache);
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline)) if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
{ {

View File

@@ -109,7 +109,7 @@ struct hub_user
struct hub_user_info id; /** Contains nick name and CID */ struct hub_user_info id; /** Contains nick name and CID */
enum auth_credentials credentials; /** see enum user_credentials */ enum auth_credentials credentials; /** see enum user_credentials */
enum user_state state; /** see enum user_state */ enum user_state state; /** see enum user_state */
uint32_t flags; /** see enum user_features */ uint32_t flags; /** see enum user_flags */
struct linked_list* feature_cast; /** Features supported by feature cast */ struct linked_list* feature_cast; /** Features supported by feature cast */
struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */ struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */
struct hub_info* hub; /** The hub instance this user belong to */ struct hub_info* hub; /** The hub instance this user belong to */

View File

@@ -162,7 +162,7 @@ int uman_remove(struct hub_info* hub, struct hub_user* user)
} }
else else
{ {
assert(!"negative count!"); uhub_assert(!"negative count!");
} }
hub->users->shared_size -= user->limits.shared_size; hub->users->shared_size -= user->limits.shared_size;

View File

@@ -114,13 +114,6 @@ int net_destroy()
return -1; return -1;
} }
#ifdef USE_LIBEVENT
struct event_base* net_get_evbase()
{
return net_evbase;
}
#endif
static void net_error_out(int fd, const char* func) static void net_error_out(int fd, const char* func)
{ {
int err = net_error(); int err = net_error();
@@ -531,6 +524,7 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t
sin6.sin6_family = AF_INET6; sin6.sin6_family = AF_INET6;
sin6.sin6_port = 0; sin6.sin6_port = 0;
sin6.sin6_addr = *addr6; sin6.sin6_addr = *addr6;
sin6.sin6_scope_id = 0;
size = sizeof(sin6); size = sizeof(sin6);
addr = (LPSOCKADDR) &sin6; addr = (LPSOCKADDR) &sin6;
break; break;

View File

@@ -51,8 +51,6 @@ extern int net_initialize();
*/ */
extern int net_destroy(); extern int net_destroy();
extern struct event_base* net_get_evbase();
/** /**
* @return the number of sockets currrently being monitored. * @return the number of sockets currrently being monitored.
*/ */

View File

@@ -55,7 +55,7 @@ int net_backend_poll_select(struct net_backend* data, int ms)
struct net_backend_select* backend = (struct net_backend_select*) data; struct net_backend_select* backend = (struct net_backend_select*) data;
tval.tv_sec = ms / 1000; tval.tv_sec = ms / 1000;
tval.tv_usec = ((ms % 1000) * 1000); // FIXME: correct? tval.tv_usec = (ms % 1000) * 1000;
FD_ZERO(&backend->rfds); FD_ZERO(&backend->rfds);
FD_ZERO(&backend->wfds); FD_ZERO(&backend->wfds);
@@ -78,10 +78,11 @@ int net_backend_poll_select(struct net_backend* data, int ms)
res = select(backend->maxfd, &backend->rfds, &backend->wfds, &backend->xfds, &tval); res = select(backend->maxfd, &backend->rfds, &backend->wfds, &backend->xfds, &tval);
if (res == -1) if (res == -1)
{ {
if (net_error() == EINTR)
return 0;
printf("Error: %d\n", net_error()); printf("Error: %d\n", net_error());
} }
if (res == -1 && net_error() == EINTR)
return 0;
return res; return res;
} }

View File

@@ -35,6 +35,19 @@ struct plugin_command
struct linked_list* args; struct linked_list* args;
}; };
struct plugin_command_arg_data
{
enum plugin_command_arg_type type;
union {
int integer;
char* string;
struct plugin_user* user;
struct ip_addr_encap* address;
struct ip_range* range;
enum auth_credentials credentials;
} data;
};
typedef int (*plugin_command_handler)(struct plugin_handle*, struct plugin_user* to, struct plugin_command*); typedef int (*plugin_command_handler)(struct plugin_handle*, struct plugin_user* to, struct plugin_command*);
struct plugin_command_handle struct plugin_command_handle
@@ -62,18 +75,5 @@ struct plugin_command_handle
PTR->description = DESC; \ PTR->description = DESC; \
} while (0) } while (0)
extern int plugin_command_add(struct plugin_handle*, struct plugin_command_handle*);
extern int plugin_command_del(struct plugin_handle*, struct plugin_command_handle*);
/**
* Send a message to a user.
* From the user's perspective the message will originate from the hub.
*/
extern int plugin_command_send_message(struct plugin_handle*, struct plugin_user* to, const char* message);
/**
* Send a reply to a command.
*/
extern int plugin_command_send_reply(struct plugin_handle*, struct plugin_user* user, struct plugin_command* command, const char* message);
#endif /* HAVE_UHUB_PLUGIN_API_H */ #endif /* HAVE_UHUB_PLUGIN_API_H */

View File

@@ -29,13 +29,6 @@
#include "util/ipcalc.h" #include "util/ipcalc.h"
#include "plugin_api/types.h" #include "plugin_api/types.h"
typedef plugin_st (*on_chat_msg_t)(struct plugin_handle*, struct plugin_user* from, const char* message);
typedef plugin_st (*on_private_msg_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* message);
typedef plugin_st (*on_search_t)(struct plugin_handle*, struct plugin_user* from, const char* data);
typedef plugin_st (*on_search_result_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* data);
typedef plugin_st (*on_p2p_connect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
typedef plugin_st (*on_p2p_revconnect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
typedef void (*on_connection_accepted_t)(struct plugin_handle*, struct ip_addr_encap*); typedef void (*on_connection_accepted_t)(struct plugin_handle*, struct ip_addr_encap*);
typedef void (*on_connection_refused_t)(struct plugin_handle*, struct ip_addr_encap*); typedef void (*on_connection_refused_t)(struct plugin_handle*, struct ip_addr_encap*);
@@ -51,12 +44,18 @@ typedef void (*on_hub_reloaded_t)(struct plugin_handle*, struct plugin_hub_info*
typedef void (*on_hub_shutdown_t)(struct plugin_handle*, struct plugin_hub_info*); typedef void (*on_hub_shutdown_t)(struct plugin_handle*, struct plugin_hub_info*);
typedef void (*on_hub_error_t)(struct plugin_handle*, struct plugin_hub_info*, const char* message); typedef void (*on_hub_error_t)(struct plugin_handle*, struct plugin_hub_info*, const char* message);
typedef plugin_st (*on_change_nick_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick);
typedef plugin_st (*on_check_ip_early_t)(struct plugin_handle*, struct ip_addr_encap*); typedef plugin_st (*on_check_ip_early_t)(struct plugin_handle*, struct ip_addr_encap*);
typedef plugin_st (*on_check_ip_late_t)(struct plugin_handle*, struct ip_addr_encap*); typedef plugin_st (*on_check_ip_late_t)(struct plugin_handle*, struct plugin_user*, struct ip_addr_encap*);
typedef plugin_st (*on_validate_nick_t)(struct plugin_handle*, const char* nick); typedef plugin_st (*on_validate_nick_t)(struct plugin_handle*, const char* nick);
typedef plugin_st (*on_validate_cid_t)(struct plugin_handle*, const char* cid); typedef plugin_st (*on_validate_cid_t)(struct plugin_handle*, const char* cid);
typedef plugin_st (*on_change_nick_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick);
typedef plugin_st (*on_chat_msg_t)(struct plugin_handle*, struct plugin_user* from, const char* message);
typedef plugin_st (*on_private_msg_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* message);
typedef plugin_st (*on_search_t)(struct plugin_handle*, struct plugin_user* from, const char* data);
typedef plugin_st (*on_search_result_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* data);
typedef plugin_st (*on_p2p_connect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
typedef plugin_st (*on_p2p_revconnect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
typedef plugin_st (*auth_get_user_t)(struct plugin_handle*, const char* nickname, struct auth_info* info); typedef plugin_st (*auth_get_user_t)(struct plugin_handle*, const char* nickname, struct auth_info* info);
typedef plugin_st (*auth_register_user_t)(struct plugin_handle*, struct auth_info* user); typedef plugin_st (*auth_register_user_t)(struct plugin_handle*, struct auth_info* user);
@@ -65,6 +64,7 @@ typedef plugin_st (*auth_delete_user_t)(struct plugin_handle*, struct auth_info*
/** /**
* These are callbacks used for the hub to invoke functions in plugins. * These are callbacks used for the hub to invoke functions in plugins.
* The marked ones are not being called yet.
*/ */
struct plugin_funcs struct plugin_funcs
{ {
@@ -76,17 +76,20 @@ struct plugin_funcs
on_user_login_t on_user_login; /* A user has successfully logged in to the hub */ on_user_login_t on_user_login; /* A user has successfully logged in to the hub */
on_user_login_error_t on_user_login_error; /* A user has failed to log in to the hub */ on_user_login_error_t on_user_login_error; /* A user has failed to log in to the hub */
on_user_logout_t on_user_logout; /* A user has logged out of the hub (was previously logged in) */ on_user_logout_t on_user_logout; /* A user has logged out of the hub (was previously logged in) */
on_user_nick_change_t on_user_nick_change; /* A user has changed nickname */ /* ! */ on_user_nick_change_t on_user_nick_change; /* A user has changed nickname */
on_user_update_error_t on_user_update_error;/* A user has failed to update - nickname, etc. */ on_user_update_error_t on_user_update_error;/* A user has failed to update - nickname, etc. */
on_user_chat_msg_t on_user_chat_message;/* A user has sent a public chat message */ on_user_chat_msg_t on_user_chat_message;/* A user has sent a public chat message */
// Log hub events // Log hub events
on_hub_started_t on_hub_started; /* Triggered just after plugins are loaded and the hub is started. */ /* ! */ on_hub_started_t on_hub_started; /* Triggered just after plugins are loaded and the hub is started. */
on_hub_reloaded_t on_hub_reloaded; /* Triggered immediately after hub configuration is reloaded. */ /* ! */ on_hub_reloaded_t on_hub_reloaded; /* Triggered immediately after hub configuration is reloaded. */
on_hub_shutdown_t on_hub_shutdown; /* Triggered just before the hub is being shut down and before plugins are unloaded. */ /* ! */ on_hub_shutdown_t on_hub_shutdown; /* Triggered just before the hub is being shut down and before plugins are unloaded. */
on_hub_error_t on_hub_error; /* Triggered for log-worthy error messages */ /* ! */ on_hub_error_t on_hub_error; /* Triggered for log-worthy error messages */
// Activity events (can be intercepted and refused/accepted by a plugin) // Activity events (can be intercepted and refused/accepted by a plugin)
on_check_ip_early_t on_check_ip_early; /* A user has just connected (can be intercepted) */
/* ! */ on_check_ip_late_t on_check_ip_late; /* A user has logged in (can be intercepted) */
/* ! */ on_change_nick_t on_change_nick; /* A user wants to change his nick (can be intercepted) */
on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */ on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */
on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */ on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */
on_search_t on_search; /* A search is about to be sent (can be intercepted) */ on_search_t on_search; /* A search is about to be sent (can be intercepted) */
@@ -100,12 +103,11 @@ struct plugin_funcs
auth_update_user_t auth_update_user; /* Update a registered user */ auth_update_user_t auth_update_user; /* Update a registered user */
auth_delete_user_t auth_delete_user; /* Delete a registered user */ auth_delete_user_t auth_delete_user; /* Delete a registered user */
// Login check functions
on_check_ip_early_t login_check_ip_early;
on_check_ip_late_t login_check_ip_late;
}; };
struct plugin_command_handle; struct plugin_command_handle;
struct plugin_command;
struct plugin_command_arg_data;
typedef int (*hfunc_send_message)(struct plugin_handle*, struct plugin_user* user, const char* message); typedef int (*hfunc_send_message)(struct plugin_handle*, struct plugin_user* user, const char* message);
typedef int (*hfunc_send_status)(struct plugin_handle*, struct plugin_user* to, int code, const char* message); typedef int (*hfunc_send_status)(struct plugin_handle*, struct plugin_user* to, int code, const char* message);
@@ -113,6 +115,14 @@ typedef int (*hfunc_user_disconnect)(struct plugin_handle*, struct plugin_user*
typedef int (*hfunc_command_add)(struct plugin_handle*, struct plugin_command_handle*); typedef int (*hfunc_command_add)(struct plugin_handle*, struct plugin_command_handle*);
typedef int (*hfunc_command_del)(struct plugin_handle*, struct plugin_command_handle*); typedef int (*hfunc_command_del)(struct plugin_handle*, struct plugin_command_handle*);
typedef size_t (*hfunc_command_arg_reset)(struct plugin_handle*, struct plugin_command*);
typedef struct plugin_command_arg_data* (*hfunc_command_arg_next)(struct plugin_handle*, struct plugin_command*, enum plugin_command_arg_type);
typedef char* (*hfunc_get_hub_name)(struct plugin_handle*);
typedef void (*hfunc_set_hub_name)(struct plugin_handle*, const char*);
typedef char* (*hfunc_get_hub_description)(struct plugin_handle*);
typedef void (*hfunc_set_hub_description)(struct plugin_handle*, const char*);
/** /**
* These are functions created and initialized by the hub and which can be used * These are functions created and initialized by the hub and which can be used
* by plugins to access functionality internal to the hub. * by plugins to access functionality internal to the hub.
@@ -124,9 +134,14 @@ struct plugin_hub_funcs
hfunc_user_disconnect user_disconnect; hfunc_user_disconnect user_disconnect;
hfunc_command_add command_add; hfunc_command_add command_add;
hfunc_command_del command_del; hfunc_command_del command_del;
hfunc_command_arg_reset command_arg_reset;
hfunc_command_arg_next command_arg_next;
hfunc_get_hub_name get_name;
hfunc_set_hub_name set_name;
hfunc_get_hub_description get_description;
hfunc_set_hub_description set_description;
}; };
struct plugin_handle struct plugin_handle
{ {
struct uhub_plugin* handle; /* Must NOT be modified by the plugin */ struct uhub_plugin* handle; /* Must NOT be modified by the plugin */

View File

@@ -93,4 +93,15 @@ struct ban_info
time_t expiry; /* Time when the ban record expires */ time_t expiry; /* Time when the ban record expires */
}; };
enum plugin_command_arg_type
{
plugin_cmd_arg_type_integer,
plugin_cmd_arg_type_string,
plugin_cmd_arg_type_user,
plugin_cmd_arg_type_address,
plugin_cmd_arg_type_range,
plugin_cmd_arg_type_credentials,
};
#endif /* HAVE_UHUB_PLUGIN_TYPES_H */ #endif /* HAVE_UHUB_PLUGIN_TYPES_H */

View File

@@ -39,6 +39,37 @@ struct sql_data
sqlite3* db; sqlite3* db;
}; };
static int null_callback(void* ptr, int argc, char **argv, char **colName) { return 0; }
static int sql_execute(struct sql_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);
#ifdef DEBUG_SQL
printf("SQL: %s\n", query);
#endif
rc = sqlite3_exec(sql->db, query, callback, ptr, &errMsg);
if (rc != SQLITE_OK)
{
#ifdef DEBUG_SQL
fprintf(stderr, "ERROR: %s\n", errMsg);
#endif
sqlite3_free(errMsg);
return -rc;
}
rc = sqlite3_changes(sql->db);
return rc;
}
static struct sql_data* parse_config(const char* line, struct plugin_handle* plugin) static struct sql_data* parse_config(const char* line, struct plugin_handle* plugin)
{ {
struct sql_data* data = (struct sql_data*) hub_malloc_zero(sizeof(struct sql_data)); struct sql_data* data = (struct sql_data*) hub_malloc_zero(sizeof(struct sql_data));
@@ -178,17 +209,42 @@ static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, st
static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user) static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user)
{ {
struct sql_data* sql = (struct sql_data*) plugin->ptr; struct sql_data* sql = (struct sql_data*) plugin->ptr;
if (sql->exclusive) char* nick = strdup(sql_escape_string(user->nickname));
char* pass = strdup(sql_escape_string(user->password));
const char* cred = auth_cred_to_string(user->credentials);
int rc = sql_execute(sql, null_callback, NULL, "INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", nick, pass, cred);
free(nick);
free(pass);
if (rc <= 0)
{
fprintf(stderr, "Unable to add user \"%s\"\n", user->nickname);
return st_deny; return st_deny;
return st_default; }
return st_allow;
} }
static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user) static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user)
{ {
struct sql_data* sql = (struct sql_data*) plugin->ptr; struct sql_data* sql = (struct sql_data*) plugin->ptr;
if (sql->exclusive)
char* nick = strdup(sql_escape_string(user->nickname));
char* pass = strdup(sql_escape_string(user->password));
const char* cred = auth_cred_to_string(user->credentials);
int rc = sql_execute(sql, null_callback, NULL, "INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", nick, pass, cred);
free(nick);
free(pass);
if (rc <= 0)
{
fprintf(stderr, "Unable to add user \"%s\"\n", user->nickname);
return st_deny; return st_deny;
return st_default; }
return st_allow;
} }
static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user) static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user)
@@ -201,7 +257,7 @@ static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* use
int plugin_register(struct plugin_handle* plugin, const char* config) int plugin_register(struct plugin_handle* plugin, const char* config)
{ {
PLUGIN_INITIALIZE(plugin, "SQLite authentication plugin", "0.1", "Authenticate users based on a SQLite database."); PLUGIN_INITIALIZE(plugin, "SQLite authentication plugin", "1.0", "Authenticate users based on a SQLite database.");
// Authentication actions. // Authentication actions.
plugin->funcs.auth_get_user = get_user; plugin->funcs.auth_get_user = get_user;

View File

@@ -129,13 +129,14 @@ static int command_history(struct plugin_handle* plugin, struct plugin_user* use
{ {
struct cbuffer* buf; struct cbuffer* buf;
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
int maxlines = 0; struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_integer);
int maxlines;
if (!list_size(data->chat_history)) if (!list_size(data->chat_history))
return command_status(plugin, user, cmd, cbuf_create_const("No messages.")); return command_status(plugin, user, cmd, cbuf_create_const("No messages."));
if (list_size(cmd->args) > 0) if (arg)
maxlines = (int) (intptr_t) ((intptr_t*) (void*) list_get_first(cmd->args)); maxlines = arg->data.integer;
else else
maxlines = data->history_default; maxlines = data->history_default;
@@ -159,7 +160,7 @@ static struct chat_history_data* parse_config(const char* line, struct plugin_ha
struct cfg_tokens* tokens = cfg_tokenize(line); struct cfg_tokens* tokens = cfg_tokenize(line);
char* token = cfg_token_get_first(tokens); char* token = cfg_token_get_first(tokens);
assert(data != NULL); uhub_assert(data != NULL);
data->history_max = 200; data->history_max = 200;
data->history_default = 25; data->history_default = 25;

102
src/plugins/mod_topic.c Normal file
View File

@@ -0,0 +1,102 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, 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/memory.h"
#include "util/cbuffer.h"
struct topic_plugin_data
{
struct plugin_command_handle* topic;
struct plugin_command_handle* cleartopic;
struct plugin_command_handle* showtopic;
};
static int command_topic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_string);
plugin->hub.set_description(plugin, arg ? arg->data.string : NULL);
cbuf_append_format(buf, "*** %s: Topic set to \"%s\"", cmd->prefix, arg->data.string);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
return 0;
}
static int command_cleartopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
plugin->hub.set_description(plugin, NULL);
cbuf_append_format(buf, "*** %s: Topic cleared.", cmd->prefix);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
return 0;
}
static int command_showtopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
char* topic = plugin->hub.get_description(plugin);
cbuf_append_format(buf, "*** %s: Current topic is: \"%s\"", cmd->prefix, topic);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
hub_free(topic);
return 0;
}
int plugin_register(struct plugin_handle* plugin, const char* config)
{
struct topic_plugin_data* data = (struct topic_plugin_data*) hub_malloc(sizeof(struct topic_plugin_data));
data->topic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
data->cleartopic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
data->showtopic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
PLUGIN_INITIALIZE(plugin, "Topic plugin", "1.0", "Add commands for changing the hub topic (description)");
PLUGIN_COMMAND_INITIALIZE(data->topic, (void*) data, "topic", "+m", auth_cred_operator, command_topic_handler, "Set new topic");
PLUGIN_COMMAND_INITIALIZE(data->cleartopic, (void*) data, "cleartopic", "", auth_cred_operator, command_cleartopic_handler, "Clear the current topic");
PLUGIN_COMMAND_INITIALIZE(data->showtopic, (void*) data, "showtopic", "", auth_cred_guest, command_showtopic_handler, "Shows the current topic");
plugin->hub.command_add(plugin, data->topic);
plugin->hub.command_add(plugin, data->cleartopic);
plugin->hub.command_add(plugin, data->showtopic);
plugin->ptr = data;
return 0;
}
int plugin_unregister(struct plugin_handle* plugin)
{
struct topic_plugin_data* data = (struct topic_plugin_data*) plugin->ptr;
plugin->hub.command_del(plugin, data->topic);
plugin->hub.command_del(plugin, data->cleartopic);
plugin->hub.command_del(plugin, data->showtopic);
hub_free(data->topic);
hub_free(data->cleartopic);
hub_free(data->showtopic);
hub_free(data);
plugin->ptr = NULL;
return 0;
}

View File

@@ -73,6 +73,7 @@
#include <time.h> #include <time.h>
#if !defined(WIN32) #if !defined(WIN32)
#include <inttypes.h>
#include <unistd.h> #include <unistd.h>
#include <grp.h> #include <grp.h>
#include <pwd.h> #include <pwd.h>
@@ -88,12 +89,13 @@
#define HAVE_GETRLIMIT #define HAVE_GETRLIMIT
#endif #endif
/* printf and size_t support */ /* printf support for size_t and uint64_t */
#if defined(WIN32) #if defined(WIN32)
/* Windows uses %Iu for size_t */
#define PRINTF_SIZE_T "%Iu" #define PRINTF_SIZE_T "%Iu"
#define PRINTF_UINT64_T "%I64u"
#else #else
#define PRINTF_SIZE_T "%zu" #define PRINTF_SIZE_T "%zu"
#define PRINTF_UINT64_T ("%" PRIu64)
#endif #endif
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
*/ */
#include "uhub.h" #include "uhub.h"
#include "util/misc.h"
#include <sqlite3.h> #include <sqlite3.h>
// #define DEBUG_SQL // #define DEBUG_SQL
@@ -104,6 +105,59 @@ static const char* validate_cred(const char* cred_str)
exit(1); exit(1);
} }
static const char* validate_username(const char* username)
{
const char* tmp;
// verify length
if (strlen(username) > MAX_NICK_LEN)
{
fprintf(stderr, "User name is too long.\n");
exit(1);
}
/* Nick must not start with a space */
if (is_white_space(username[0]))
{
fprintf(stderr, "User name cannot start with white space.\n");
exit(1);
}
/* Check for ASCII values below 32 */
for (tmp = username; *tmp; tmp++)
if ((*tmp < 32) && (*tmp > 0))
{
fprintf(stderr, "User name contains illegal characters.\n");
exit(1);
}
if (!is_valid_utf8(username))
{
fprintf(stderr, "User name must be utf-8 encoded.\n");
exit(1);
}
return username;
}
static const char* validate_password(const char* password)
{
// verify length
if (strlen(password) > MAX_PASS_LEN)
{
fprintf(stderr, "Password is too long.\n");
exit(1);
}
if (!is_valid_utf8(password))
{
fprintf(stderr, "Password must be utf-8 encoded.\n");
exit(1);
}
return password;
}
static void open_database() static void open_database()
{ {
@@ -202,8 +256,8 @@ static int add(size_t argc, const char** argv)
if (argc < 2) if (argc < 2)
print_usage("username password [credentials = user]"); print_usage("username password [credentials = user]");
user = sql_escape_string(argv[0]); user = sql_escape_string(validate_username(argv[0]));
pass = sql_escape_string(argv[1]); pass = sql_escape_string(validate_password(argv[1]));
cred = validate_cred(argv[2] ? argv[2] : "user"); cred = validate_cred(argv[2] ? argv[2] : "user");
rc = sql_execute("INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", user, pass, cred); rc = sql_execute("INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", user, pass, cred);
@@ -253,7 +307,7 @@ static int pass(size_t argc, const char** argv)
print_usage("username password"); print_usage("username password");
user = sql_escape_string(argv[0]); user = sql_escape_string(argv[0]);
pass = sql_escape_string(argv[1]); pass = sql_escape_string(validate_password(argv[1]));
rc = sql_execute("UPDATE users SET password = '%s' WHERE nickname = '%s';", pass, user); rc = sql_execute("UPDATE users SET password = '%s' WHERE nickname = '%s';", pass, user);
@@ -275,7 +329,7 @@ static int del(size_t argc, const char** argv)
char* user = NULL; char* user = NULL;
int rc; int rc;
if (argc < 2) if (argc < 1)
print_usage("username"); print_usage("username");
user = sql_escape_string(argv[0]); user = sql_escape_string(argv[0]);
@@ -307,11 +361,11 @@ void main_usage(const char* binary)
"\n" "\n"
"Parameters:\n" "Parameters:\n"
" 'filename' is a database file\n" " 'filename' is a database file\n"
" 'username' is a nickname (UTF-8, up to 64 bytes)\n" " 'username' is a nickname (UTF-8, up to %i bytes)\n"
" 'password' is a password (UTF-8, up to 64 bytes)\n" " 'password' is a password (UTF-8, up to %i bytes)\n"
" 'credentials' is one of 'admin', 'super', 'op', 'user'\n" " 'credentials' is one of 'admin', 'super', 'op', 'user'\n"
"\n" "\n"
, binary); , binary, MAX_NICK_LEN, MAX_PASS_LEN);
} }
int main(int argc, char** argv) int main(int argc, char** argv)
@@ -330,7 +384,7 @@ int main(int argc, char** argv)
for (; n < sizeof(COMMANDS) / sizeof(COMMANDS[0]); n++) for (; n < sizeof(COMMANDS) / sizeof(COMMANDS[0]); n++)
{ {
if (!strcmp(command, COMMANDS[n].command)) if (!strcmp(command, COMMANDS[n].command))
return COMMANDS[n].handle(argc - 2, (const char**) &argv[3]); return COMMANDS[n].handle(argc - 3, (const char**) &argv[3]);
} }
// Unknown command! // Unknown command!

View File

@@ -88,6 +88,7 @@ extern "C" {
#include "core/route.h" #include "core/route.h"
#include "core/pluginloader.h" #include "core/pluginloader.h"
#include "core/hub.h" #include "core/hub.h"
#include "core/command_parser.h"
#include "core/commands.h" #include "core/commands.h"
#include "core/inf.h" #include "core/inf.h"
#include "core/hubevent.h" #include "core/hubevent.h"

View File

@@ -73,10 +73,10 @@ struct cfg_tokens* cfg_tokenize(const char* line)
} }
break; break;
case '\"': case '"':
if (backslash) if (backslash)
{ {
ADD_CHAR('\"'); ADD_CHAR('"');
backslash = 0; backslash = 0;
} }
else if (quote) else if (quote)

View File

@@ -32,8 +32,13 @@ struct linked_list* list_create()
void list_destroy(struct linked_list* list) void list_destroy(struct linked_list* list)
{ {
if (list) if (list)
{
uhub_assert(list->size == 0);
uhub_assert(list->first == NULL);
uhub_assert(list->last == NULL);
hub_free(list); hub_free(list);
} }
}
void list_clear(struct linked_list* list, void (*free_handle)(void* ptr)) void list_clear(struct linked_list* list, void (*free_handle)(void* ptr))
@@ -79,7 +84,7 @@ void list_append(struct linked_list* list, void* data_ptr)
void list_remove(struct linked_list* list, void* data_ptr) void list_remove(struct linked_list* list, void* data_ptr)
{ {
struct node* node = list->first; struct node* node = list->first;
assert(data_ptr); uhub_assert(data_ptr);
list->iterator = NULL; list->iterator = NULL;
@@ -102,7 +107,7 @@ void list_remove(struct linked_list* list, void* data_ptr)
hub_free(node); hub_free(node);
list->size--; list->size--;
break; return;
} }
node = node->next; node = node->next;
} }

View File

@@ -244,7 +244,7 @@ int file_read_lines(const char* file, void* data, file_line_handler_t handler)
return -2; return -2;
} }
ret = read(fd, buf, MAX_RECV_BUF); ret = read(fd, buf, MAX_RECV_BUF-1);
close(fd); close(fd);
if (ret < 0) if (ret < 0)
@@ -258,7 +258,9 @@ int file_read_lines(const char* file, void* data, file_line_handler_t handler)
return 0; return 0;
} }
/* Parse configuaration */ buf[ret] = 0;
/* Parse configuration */
split_data.handler = handler; split_data.handler = handler;
split_data.data = data; split_data.data = data;
@@ -303,47 +305,19 @@ int is_number(const char* value, int* num)
} }
/*
* FIXME: -INTMIN is wrong!
*/
const char* uhub_itoa(int val) const char* uhub_itoa(int val)
{ {
size_t i;
int value;
static char buf[22]; static char buf[22];
memset(buf, 0, sizeof(buf));
if (!val)
{
buf[0] = '0';
buf[1] = '\0';
return buf;
}
i = sizeof(buf) - 1;
for (value = abs(val); value && i > 0; value /= 10)
buf[--i] = "0123456789"[value % 10];
if (val < 0 && i > 0) return snprintf(buf, sizeof(buf), "%d", val) < 0 ? NULL : buf;
buf[--i] = '-';
return buf+i;
} }
const char* uhub_ulltoa(uint64_t val) const char* uhub_ulltoa(uint64_t val)
{ {
size_t i; static char buf[22];
static char buf[22] = { 0, };
memset(buf, 0, sizeof(buf));
if (!val) return snprintf(buf, sizeof(buf), PRINTF_UINT64_T, val) < 0 ? NULL : buf;
{
buf[0] = '0';
buf[1] = '\0';
return buf;
}
i = sizeof(buf) - 1;
for (; val && i > 0; val /= 10)
buf[--i] = "0123456789"[val % 10];
return buf+i;
} }

View File

@@ -53,7 +53,11 @@ extern int file_read_lines(const char* file, void* data, file_line_handler_t han
*/ */
extern int string_to_boolean(const char* str, int* boolean); extern int string_to_boolean(const char* str, int* boolean);
/**
* Convert number to string.
* Note: these functions are neither thread-safe nor reentrant.
* @return pointer to the resulting string, NULL on error
*/
extern const char* uhub_itoa(int val); extern const char* uhub_itoa(int val);
extern const char* uhub_ulltoa(uint64_t val); extern const char* uhub_ulltoa(uint64_t val);

View File

@@ -1,42 +1,18 @@
#!/usr/bin/perl #!/usr/bin/perl
# use script # Usage:
# sqlite3 users.db < `tools/convert_to_sqlite.pl /etc/uhub/users.conf` # cat /etc/uhub/users.conf | tools/convert_to_sqlite.pl | sqlite3 users.db
my $input = $ARGV[0];
open (FILE, "$input") || die "# Unable to open input file $input: $!";
my @lines = <FILE>;
close (FILE);
print "CREATE TABLE users(nickname CHAR(64) UNIQUE, password CHAR(64), credentials CHAR(5));\n";
foreach my $line (@lines) {
chomp($line);
$line =~ s/#.*//g;
next if ($line =~ /^\s*$/);
if ($line =~ /^\s*user_(op|admin|super|reg)\s*(.+):(.+)\s*/)
{
my $cred = $1;
my $nick = $2;
my $pass = $3;
$nick =~ s/'/\\'/g;
$pass =~ s/'/\\'/g;
print "INSERT INTO users VALUES('" . $nick . "', '" . $pass . "', '" . $cred . "');\n";
}
else
{
# print "# Warning: Unrecognized line: \"" . $line . "\"\n";
}
}
print <<_;
CREATE TABLE users(
nickname CHAR(64) UNIQUE,
password CHAR(64),
credentials CHAR(5),
created TIMESTAMP DEFAULT (DATETIME('NOW')),
activity TIMESTAMP DEFAULT (DATETIME('NOW'))
);
_
sub e($) { (my $v = shift) =~ s/'/\\'/g; $v }
s{^\s*user_(op|admin|super|reg)\s+([^#\s]+):([^#\s]+)}{
printf "INSERT INTO users (nickname, password, credentials) VALUES('%s','%s','%s');\n", e $2, e $3, $1
}eg while(<>);

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9BBAEFDA-8E0E-4E7F-B8B6-00A3432FC45B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>mod_topic</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)..\src;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)vs2010\$(Configuration);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXAMPLE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(SolutionDir)\$(Configuration)\uhub_utils.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXAMPLE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\plugins\mod_topic.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -32,6 +32,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uhub-passwd", "uhub-passwd\
{A4FC9D62-D544-4D2A-88D7-A58529C3460B} = {A4FC9D62-D544-4D2A-88D7-A58529C3460B} {A4FC9D62-D544-4D2A-88D7-A58529C3460B} = {A4FC9D62-D544-4D2A-88D7-A58529C3460B}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_topic", "plugins\mod_topic\mod_topic.vcxproj", "{9BBAEFDA-8E0E-4E7F-B8B6-00A3432FC45B}"
ProjectSection(ProjectDependencies) = postProject
{0A3C1519-D877-47D9-A82E-40AC1BC79D75} = {0A3C1519-D877-47D9-A82E-40AC1BC79D75}
{98D8BFE9-DACD-40E1-B7BE-C9079ABF832E} = {98D8BFE9-DACD-40E1-B7BE-C9079ABF832E}
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
@@ -66,6 +72,10 @@ Global
{E92EB860-AE9E-4532-A75F-0929A7BCF6D0}.Debug|Win32.Build.0 = Debug|Win32 {E92EB860-AE9E-4532-A75F-0929A7BCF6D0}.Debug|Win32.Build.0 = Debug|Win32
{E92EB860-AE9E-4532-A75F-0929A7BCF6D0}.Release|Win32.ActiveCfg = Release|Win32 {E92EB860-AE9E-4532-A75F-0929A7BCF6D0}.Release|Win32.ActiveCfg = Release|Win32
{E92EB860-AE9E-4532-A75F-0929A7BCF6D0}.Release|Win32.Build.0 = Release|Win32 {E92EB860-AE9E-4532-A75F-0929A7BCF6D0}.Release|Win32.Build.0 = Release|Win32
{9BBAEFDA-8E0E-4E7F-B8B6-00A3432FC45B}.Debug|Win32.ActiveCfg = Debug|Win32
{9BBAEFDA-8E0E-4E7F-B8B6-00A3432FC45B}.Debug|Win32.Build.0 = Debug|Win32
{9BBAEFDA-8E0E-4E7F-B8B6-00A3432FC45B}.Release|Win32.ActiveCfg = Release|Win32
{9BBAEFDA-8E0E-4E7F-B8B6-00A3432FC45B}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -85,6 +85,7 @@
<ClCompile Include="..\src\adc\sid.c" /> <ClCompile Include="..\src\adc\sid.c" />
<ClCompile Include="..\src\core\auth.c" /> <ClCompile Include="..\src\core\auth.c" />
<ClCompile Include="..\src\core\commands.c" /> <ClCompile Include="..\src\core\commands.c" />
<ClCompile Include="..\src\core\command_parser.c" />
<ClCompile Include="..\src\core\config.c" /> <ClCompile Include="..\src\core\config.c" />
<ClCompile Include="..\src\core\eventqueue.c" /> <ClCompile Include="..\src\core\eventqueue.c" />
<ClCompile Include="..\src\core\hub.c" /> <ClCompile Include="..\src\core\hub.c" />
@@ -116,6 +117,7 @@
<ClInclude Include="..\src\core\auth.h" /> <ClInclude Include="..\src\core\auth.h" />
<ClInclude Include="..\src\core\commands.h" /> <ClInclude Include="..\src\core\commands.h" />
<ClInclude Include="..\src\core\commands_builtin.h" /> <ClInclude Include="..\src\core\commands_builtin.h" />
<ClInclude Include="..\src\core\command_parser.h" />
<ClInclude Include="..\src\core\config.h" /> <ClInclude Include="..\src\core\config.h" />
<ClInclude Include="..\src\core\eventid.h" /> <ClInclude Include="..\src\core\eventid.h" />
<ClInclude Include="..\src\core\eventqueue.h" /> <ClInclude Include="..\src\core\eventqueue.h" />