-/* modcmd.c - NeonServ v5.0
+/* modcmd.c - NeonServ v5.2
* Copyright (C) 2011 Philipp Kreil (pk910)
*
* This program is free software: you can redistribute it and/or modify
struct trigger_callback *next;
};
+struct cmd_bot_alias {
+ int botid;
+ char *alias;
+
+ struct cmd_bot_alias *next;
+};
+
struct command_check_user_cache {
struct ClientSocket *client, *textclient;
struct UserNode *user;
struct ChanNode *chan, *sent_chan;
char **argv;
int argc;
- char *message;
+ char *message, *args_buffer;
struct cmd_binding *cbind;
};
static struct cmd_binding **cmd_binds;
static struct cmd_function *cmd_functions = NULL;
static struct trigger_callback *trigger_callbacks = NULL;
+static struct cmd_bot_alias *bot_aliases = NULL;
static struct ClientSocket *tmp_text_client;
static const struct default_language_entry msgtab[] = {
return 0;
}
trigger->botid = botid;
- trigger->trigger = strdup(triggerStr);
+ trigger->trigger = (triggerStr[0] ? strdup(triggerStr) : NULL);
trigger->next = chan->trigger;
chan->trigger = trigger;
return trigger->trigger;
tmp_text_client = cache->textclient;
handle_command_async(cache->client, user, cache->chan, cache->sent_chan, cache->cbind, cache->argv, cache->argc);
free(cache->message);
+ if(cache->args_buffer)
+ free(cache->args_buffer);
+ free(cache->argv);
free(cache);
}
message = strdup(message);
int bind_index = get_binds_index(message[0]);
char *args = strstr(message, " ");
+ char *args_buffer = NULL; //we need this to save a possible pointer to a allocation we need to free
if(args) {
*args = '\0';
args++;
chan = chan2;
}
}
- if(cbind->parameters) {
+ if(cbind->paramcount) {
//userdefined parameters...
+ args_buffer = malloc(MAXLEN * 2 * sizeof(*args_buffer));
+ int args_pos = 0;
char *uargs[MAXNUMPARAMS];
int uargc = 0;
- char *a,*b = cbind->parameters;
+ char *b;
+ int i;
int allargs, argi;
- do {
- a = strstr(b, " ");
- if(a) *a = '\0';
+ for(i = 0; i < cbind->paramcount; i++) {
+ b = cbind->parameters[i];
if(b[0] == '%') {
b++;
if(b[strlen(b)-1] == '-') {
+ allargs = strlen(b)-1;
+ b[allargs] = '\0';
+ argi = atoi(b);
+ b[allargs] = '-';
allargs = 1;
- b[strlen(b)-1] = '\0';
+ } else if(b[strlen(b)-1] == '+') {
+ allargs = strlen(b)-1;
+ b[allargs] = '\0';
argi = atoi(b);
- b[strlen(b)-1] = '-';
+ b[allargs] = '+';
+ allargs = 2;
} else {
allargs = 0;
argi = atoi(b);
}
if(argi > 0) {
if(argi <= argc) {
- uargs[uargc++] = argv[argi-1];
- if(allargs) {
- for(argi++; argi <= argc; argi++)
- uargs[uargc++] = argv[argi-1];
+ uargs[uargc++] = args_buffer + args_pos;
+ if(allargs == 0) {
+ args_pos += sprintf(args_buffer + args_pos, "%s", argv[argi-1]) + 1;
+ } else if(allargs == 1) {
+ args_pos += sprintf(args_buffer + args_pos, "%s", argv[argi-1]) + 1;
+ for(argi++; argi <= argc; argi++) {
+ uargs[uargc++] = args_buffer + args_pos;
+ args_pos += sprintf(args_buffer + args_pos, "%s", argv[argi-1]) + 1;
+ }
+ } else if(allargs == 2) {
+ for(;argi <= argc; argi++) {
+ args_pos += sprintf(args_buffer + args_pos, (allargs ? "%s" : " %s"), argv[argi-1]);
+ allargs = 0;
+ }
+ args_pos++;
}
+ } else if((cbind->func->flags & CMDFLAG_EMPTY_ARGS)) {
+ uargs[uargc++] = args_buffer + args_pos;
+ args_buffer[args_pos++] = '\0';
}
} else if(!strcmp(b, "c")) {
- uargs[uargc++] = (chan ? chan->name : NULL);
+ uargs[uargc++] = args_buffer + args_pos;
+ args_pos += sprintf(args_buffer + args_pos, "%s", (chan ? chan->name : "")) + 1;
} else if(!strcmp(b, "n")) {
- uargs[uargc++] = user->nick;
+ uargs[uargc++] = args_buffer + args_pos;
+ args_pos += sprintf(args_buffer + args_pos, "%s", user->nick) + 1;
}
} else {
- uargs[uargc++] = b;
- }
- if(a) {
- *a = ' ';
- b = a+1;
+ uargs[uargc++] = args_buffer + args_pos;
+ args_pos += sprintf(args_buffer + args_pos, "%s", b) + 1;
}
- } while(a);
+ }
argv = uargs;
argc = uargc;
}
data->chan = chan;
data->sent_chan = sent_chan;
data->message = message;
+ data->args_buffer = args_buffer;
data->cbind = cbind;
data->textclient = tmp_text_client;
get_userauth(user, command_checked_auth, data);
}
}
free(message);
+ if(args_buffer)
+ free(args_buffer);
}
static void handle_command_async(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct ChanNode *sent_chan, struct cmd_binding *cbind, char **argv, int argc) {
printf_mysql_query("SELECT `channel_pubcmd` FROM `channels` WHERE `channel_name` = '%s'", escape_string(sent_chan->name));
res = mysql_use();
if ((row = mysql_fetch_row(res)) != NULL) {
- uaccess = getChannelAccess(user, sent_chan, 1);
- if(row[0] && uaccess < atoi(row[0])) { //NOTE: HARDCODED DEFAULT: pubcmd = 0
+ uaccess = getChannelAccess(user, sent_chan);
+ if(row[0] && uaccess < atoi(row[0]) && !isGodMode(user)) { //NOTE: HARDCODED DEFAULT: pubcmd = 0
reply(tmp_text_client, user, "MODCMD_PUBCMD", sent_chan->name);
return;
}
chan->flags |= CHANFLAG_CHAN_REGISTERED;
chan->channel_id = atoi(row[0]);
if((sent_chan && sent_chan == chan) || access_count || minaccess) {
- uaccess = getChannelAccess(user, chan, 0);
+ uaccess = getChannelAccess(user, chan);
if(uaccess < minaccess && isGodMode(user)) {
eventflags |= CMDFLAG_OPLOG;
} else if(uaccess < minaccess) {
if(isUserOnChan(client->user, chan) && (client->flags & SOCKET_FLAG_PREFERRED) && !FD_ISSET(client->botid, &fds)) {
FD_SET(client->botid, &fds);
trigger = get_channel_trigger(client->botid, chan);
- if(stricmplen(message, trigger, strlen(trigger)) == 0) {
+ if(trigger && stricmplen(message, trigger, strlen(trigger)) == 0) {
handle_command(client, user, chan, message + strlen(trigger));
}
}
if(isUserOnChan(client->user, chan) && !FD_ISSET(client->botid, &fds)) {
FD_SET(client->botid, &fds);
trigger = get_channel_trigger(client->botid, chan);
- if(stricmplen(message, trigger, strlen(trigger)) == 0) {
+ if(trigger && stricmplen(message, trigger, strlen(trigger)) == 0) {
handle_command(client, user, chan, message + strlen(trigger));
}
}
int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags) {
struct cmd_function *cmdfunc;
for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
- if(cmdfunc->botid == botid && strcmp(cmdfunc->name, name) == 0)
+ if((cmdfunc->botid == botid || cmdfunc->botid == 0) && strcmp(cmdfunc->name, name) == 0)
return 0;
}
cmdfunc = malloc(sizeof(*cmdfunc));
cbind->botid = botid;
cbind->cmd = strdup(cmd);
cbind->func = func;
- cbind->parameters = NULL;
+ cbind->paramcount = 0;
cbind->global_access = 0;
cbind->channel_access = NULL;
cbind->flags = 0;
int bind_cmd_to_command(int botid, char *cmd, char *func) {
struct cmd_function *cmdfunc;
+ int fbotid = botid;
+ char *c;
+ if((c = strstr(func, "."))) {
+ *c = '\0';
+ struct cmd_bot_alias *botalias;
+ for(botalias = bot_aliases; botalias; botalias = botalias->next) {
+ if(!stricmp(botalias->alias, func)) {
+ fbotid = botalias->botid;
+ break;
+ }
+ }
+ *c = '.';
+ func = c+1;
+ }
for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
- if(cmdfunc->botid == botid && strcmp(cmdfunc->name, func) == 0)
+ if((cmdfunc->botid == fbotid || cmdfunc->botid == 0) && strcmp(cmdfunc->name, func) == 0)
break;
}
if(!cmdfunc) return 0;
cbind->cmd = strdup(cmd);
cbind->func = cmdfunc;
cbind->next = cmd_binds[bind_index];
- cbind->parameters = NULL;
+ cbind->paramcount = 0;
cbind->global_access = 0;
cbind->channel_access = NULL;
cbind->flags = 0;
else
cmd_binds[bind_index] = cbind->next;
free(cbind->cmd);
- if(cbind->parameters)
- free(cbind->parameters);
+ if(cbind->paramcount) {
+ int i;
+ for(i = 0; i < cbind->paramcount; i++)
+ free(cbind->parameters[i]);
+ }
free(cbind);
return 1;
} else
struct cmd_function *find_cmd_function(int botid, char *name) {
struct cmd_function *cmdfunc;
+ char *c;
+ if((c = strstr(name, "."))) {
+ *c = '\0';
+ struct cmd_bot_alias *botalias;
+ for(botalias = bot_aliases; botalias; botalias = botalias->next) {
+ if(!stricmp(botalias->alias, name)) {
+ botid = botalias->botid;
+ break;
+ }
+ }
+ *c = '.';
+ name = c+1;
+ }
for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
- if(cmdfunc->botid == botid && stricmp(cmdfunc->name, name) == 0)
+ if((cmdfunc->botid == botid || cmdfunc->botid == 0) && stricmp(cmdfunc->name, name) == 0)
break;
}
return cmdfunc;
for(cbind = cmd_binds[i]; cbind; cbind = next) {
next = cbind->next;
free(cbind->cmd);
- if(cbind->parameters)
- free(cbind->parameters);
+ if(cbind->paramcount) {
+ int j;
+ for(j = 0; j < cbind->paramcount; j++)
+ free(cbind->parameters[j]);
+ }
if(cbind->channel_access)
free(cbind->channel_access);
free(cbind);
next_cb = cb->next;
free(next_cb);
}
+ struct cmd_bot_alias *botalias, *next_botalias;
+ for(botalias = bot_aliases; botalias; botalias = next_botalias) {
+ next_botalias = botalias->next;
+ free(botalias->alias);
+ free(botalias);
+ }
cmd_functions = NULL;
trigger_callbacks = NULL;
+ bot_aliases = NULL;
}
void bind_set_parameters(int botid, char *cmd, char *parameters) {
struct cmd_binding *cbind;
for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
- if(cbind->parameters)
- free(cbind->parameters);
- cbind->parameters = strdup(parameters);
+ if(cbind->paramcount) {
+ int i;
+ for(i = 0; i < cbind->paramcount; i++)
+ free(cbind->parameters[i]);
+ cbind->paramcount = 0;
+ }
+ char *a, *b = parameters;
+ do {
+ a = strstr(b, " ");
+ if(a) *a = '\0';
+ cbind->parameters[cbind->paramcount++] = strdup(b);
+ if(a) b = a+1;
+ } while(a);
return;
}
}
return NULL;
}
+void bind_unbound_required_functions(int botid) {
+ struct cmd_function *cmdfunc;
+ int i, found;
+ struct cmd_binding *cbind;
+ for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
+ if((cmdfunc->flags & CMDFLAG_REQUIRED)) {
+ found = 0;
+ for(i = 0; i < 27; i++) {
+ for(cbind = cmd_binds[i]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && cbind->func == cmdfunc) {
+ found = 1;
+ break;
+ }
+ }
+ if(found)
+ break;
+ }
+ if(!found && bind_cmd_to_function(botid, cmdfunc->name, cmdfunc)) {
+ cbind = find_cmd_binding(botid, cmdfunc->name);
+ cbind->flags |= CMDFLAG_TEMPONARY_BIND;
+ }
+ }
+ }
+}
+
+void register_bot_alias(int botid, char *alias) {
+ struct cmd_bot_alias *botalias;
+ for(botalias = bot_aliases; botalias; botalias = botalias->next) {
+ if(!stricmp(botalias->alias, alias))
+ return;
+ }
+ botalias = malloc(sizeof(*botalias));
+ if (!botalias) {
+ perror("malloc() failed");
+ return;
+ }
+ botalias->botid = botid;
+ botalias->alias = strdup(alias);
+ botalias->next = bot_aliases;
+ bot_aliases = botalias;
+}
+
+struct cmd_binding *getAllBinds(struct cmd_binding *last) {
+ int bind_index;
+ if(last) {
+ if(last->next)
+ return last->next;
+ bind_index = get_binds_index(last->cmd[0]) + 1;
+ if(bind_index > 26)
+ return NULL;
+ } else
+ bind_index = 0;
+ do {
+ if(cmd_binds[bind_index])
+ return cmd_binds[bind_index];
+ bind_index++;
+ } while(bind_index < 27);
+ return NULL;
+}