Cleaned up command handling code, by splitting into multiple files.
This commit is contained in:
parent
9efe4bce57
commit
74ca5a0a33
|
@ -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 \
|
||||||
|
|
|
@ -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,6 +18,7 @@ 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;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -79,7 +81,7 @@ 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;
|
||||||
|
@ -160,66 +162,76 @@ EXO_TEST(command_parse_3, { return verify("!fail", cmd_status_not_found); });
|
||||||
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, {
|
EXO_TEST(command_argument_integer_1, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test3");
|
SETUP_COMMAND("!test3");
|
||||||
return verify_argument(cmd, type_integer) == NULL;
|
return verify_argument(cmd, type_integer) == NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_integer_2, {
|
EXO_TEST(command_argument_integer_2, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test3 10 42");
|
SETUP_COMMAND("!test3 10 42");
|
||||||
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_argument(cmd, type_integer) == NULL;
|
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_argument(cmd, type_integer) == NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_integer_3, {
|
EXO_TEST(command_argument_integer_3, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test3 10 42 6784");
|
SETUP_COMMAND("!test3 10 42 6784");
|
||||||
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_arg_integer(cmd, 6784);
|
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_arg_integer(cmd, 6784);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_user_1, {
|
EXO_TEST(command_argument_user_1, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test4 tester");
|
SETUP_COMMAND("!test4 tester");
|
||||||
return verify_arg_user(cmd, &user) ;
|
return verify_arg_user(cmd, &user) ;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_cid_1, {
|
EXO_TEST(command_argument_cid_1, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
|
SETUP_COMMAND("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
|
||||||
return verify_arg_user(cmd, &user) ;
|
return verify_arg_user(cmd, &user) ;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_cred_1, {
|
EXO_TEST(command_argument_cred_1, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test7 admin");
|
SETUP_COMMAND("!test7 admin");
|
||||||
return verify_arg_cred(cmd, auth_cred_admin);;
|
return verify_arg_cred(cmd, auth_cred_admin);;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_cred_2, {
|
EXO_TEST(command_argument_cred_2, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test7 op");
|
SETUP_COMMAND("!test7 op");
|
||||||
return verify_arg_cred(cmd, auth_cred_operator);;
|
return verify_arg_cred(cmd, auth_cred_operator);;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_cred_3, {
|
EXO_TEST(command_argument_cred_3, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test7 operator");
|
SETUP_COMMAND("!test7 operator");
|
||||||
return verify_arg_cred(cmd, auth_cred_operator);
|
return verify_arg_cred(cmd, auth_cred_operator);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_cred_4, {
|
EXO_TEST(command_argument_cred_4, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test7 super");
|
SETUP_COMMAND("!test7 super");
|
||||||
return verify_arg_cred(cmd, auth_cred_super);
|
return verify_arg_cred(cmd, auth_cred_super);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_cred_5, {
|
EXO_TEST(command_argument_cred_5, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test7 guest");
|
SETUP_COMMAND("!test7 guest");
|
||||||
return verify_arg_cred(cmd, auth_cred_guest);
|
return verify_arg_cred(cmd, auth_cred_guest);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(command_argument_cred_6, {
|
EXO_TEST(command_argument_cred_6, {
|
||||||
struct hub_command* cmd = command_parse(cbase, &user, "!test7 user");
|
SETUP_COMMAND("!test7 user");
|
||||||
return verify_arg_cred(cmd, auth_cred_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_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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 */
|
|
@ -38,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)
|
||||||
|
@ -87,50 +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;
|
|
||||||
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 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);
|
||||||
|
@ -147,246 +110,6 @@ 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;
|
|
||||||
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(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;
|
|
||||||
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(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 = 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) ? 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, arg_count;
|
size_t n, arg_count;
|
||||||
|
@ -494,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)
|
||||||
{
|
{
|
||||||
|
@ -571,7 +294,7 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc
|
||||||
|
|
||||||
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++)
|
||||||
|
@ -583,7 +306,7 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
command = data->data.command;
|
command = data->data.command;
|
||||||
if (command_is_available(command, user))
|
if (command_is_available(command, user->credentials))
|
||||||
{
|
{
|
||||||
cbuf_append_format(buf, "Usage: ");
|
cbuf_append_format(buf, "Usage: ");
|
||||||
command_get_syntax(command, buf);
|
command_get_syntax(command, buf);
|
||||||
|
|
|
@ -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
|
||||||
|
@ -26,91 +26,6 @@ struct hub_command;
|
||||||
|
|
||||||
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
|
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')" */
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
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 arguments of type struct hub_command_arg_data. Parsed from message." */
|
|
||||||
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" */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argument codes are used to automatically parse arguments
|
* Argument codes are used to automatically parse arguments
|
||||||
|
@ -181,22 +96,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*);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue