X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fmodcmd.c;h=50f71c86c138c4fea960643a6c3e8ef2908eeb03;hb=f80fa658483884289cf2585790b1cf64ef722197;hp=ecb788adce3586d542c1c6d024074a4bc88f11ad;hpb=9ae50cc35bcca24f82cd2e70c4af6a72a45c7a6f;p=NeonServV5.git diff --git a/src/modcmd.c b/src/modcmd.c index ecb788a..50f71c8 100644 --- a/src/modcmd.c +++ b/src/modcmd.c @@ -68,6 +68,8 @@ static const struct default_language_entry msgtab[] = { {"MODCMD_PRIVILEGED", "$b%s$b is a privileged command."}, /* {ARGS: "god"} */ {"MODCMD_PUBCMD", "Public commands in $b%s$b are restricted."}, /* {ARGS: "#TestChan"} */ {"MODCMD_ACCESS_DENIED", "Access denied."}, + {"MODCMD_SUBCOMMANDS", "Subcommands of %s: %s"}, /* {ARGS: "bot", "ADD, DEL, EDIT"} */ + {"MODCMD_CROSSCHAN", "You must be in %s (or on its userlist) to use this command."}, {NULL, NULL} }; @@ -78,10 +80,10 @@ static int get_binds_index(char first_char) { return 26; } -struct ClientSocket* get_prefered_bot(int botid) { +struct ClientSocket* get_botwise_prefered_bot(int botid, int clientid) { struct ClientSocket *client, *lowbot = NULL; for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->botid == botid) { + if(client->botid == botid && (botid || clientid == client->clientid)) { if((client->flags & SOCKET_FLAG_PREFERRED)) return client; else @@ -91,10 +93,10 @@ struct ClientSocket* get_prefered_bot(int botid) { return lowbot; } -static char* get_channel_trigger(int botid, struct ChanNode *chan) { +static char* get_channel_trigger(int botid, int clientid, struct ChanNode *chan) { struct trigger_cache *trigger; for(trigger = chan->trigger; trigger; trigger = trigger->next) { - if(trigger->botid == botid) + if(trigger->botid == botid && (botid || trigger->clientid == clientid)) return trigger->trigger; } struct trigger_callback *cb; @@ -104,15 +106,16 @@ static char* get_channel_trigger(int botid, struct ChanNode *chan) { } char triggerStr[TRIGGERLEN]; if(cb) - cb->func(chan, triggerStr); + cb->func(clientid, chan, triggerStr); else - strcpy(triggerStr, "+"); + triggerStr[0] = '\0'; trigger = malloc(sizeof(*trigger)); if (!trigger) { perror("malloc() failed"); return 0; } trigger->botid = botid; + trigger->clientid = clientid; trigger->trigger = (triggerStr[0] ? strdup(triggerStr) : NULL); trigger->next = chan->trigger; chan->trigger = trigger; @@ -132,6 +135,11 @@ static USERAUTH_CALLBACK(command_checked_auth) { free(cache); } +static CMD_BIND(modcmd_linker) { + //fake command for subcommands + //just empty +} + static void handle_command(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) { struct ChanNode *sent_chan = chan; if(message[0] == '#') { @@ -154,22 +162,56 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s } struct cmd_binding *cbind; for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { - if(cbind->botid == client->botid && stricmp(cbind->cmd, message) == 0) { + if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && stricmp(cbind->cmd, message) == 0) { + if(cbind->func->func == modcmd_linker) { + //links subcommands + char command[MAXLEN]; + struct cmd_binding *parent_bind = cbind; + if(args) { + char *subcmd = args; + args = strstr(args, " "); + if(args) { + *args = '\0'; + args++; + } + sprintf(command, "%s %s", parent_bind->cmd, subcmd); + for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { + if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && stricmp(cbind->cmd, command) == 0) + break; + } + if(!cbind) + break; + } else { + //list all sub commands + int commandlen = sprintf(command, "%s ", parent_bind->cmd); + char subcommands[MAXLEN]; + int subcompos = 0; + for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { + if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && stricmplen(cbind->cmd, command, commandlen) == 0) { + subcompos += sprintf(subcommands + subcompos, (subcompos ? ", %s" : "%s"), cbind->cmd + commandlen); + } + } + reply(tmp_text_client, user, "MODCMD_SUBCOMMANDS", parent_bind->cmd, subcommands); + break; + } + } if(statistics_enabled) statistics_commands++; total_triggered++; - cbind->func->triggered++; + cbind->triggered++; if((cbind->func->flags & CMDFLAG_FUNCMD)) { if(!sent_chan) break; chan = sent_chan; } //get a text bot - tmp_text_client = get_prefered_bot(client->botid); + tmp_text_client = get_botwise_prefered_bot(client->botid, (client->botid == 0 ? client->clientid : 0)); //parse the arguments... char *arga[MAXNUMPARAMS]; char **argv; int argc = 0; + int escape = 0; + int offset = 0; if(args) { while(*args) { //skip leading spaces @@ -178,8 +220,22 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s arga[argc++] = args; if (argc >= MAXNUMPARAMS) break; - while (*args != ' ' && *args) + while ((escape || *args != ' ') && *args) { + if((cbind->func->flags & CMDFLAG_ESCAPE_ARGS) && *args == '\\') { + escape = 1; + offset++; + } else if(escape) + escape = 0; + if(!escape && offset) { + args[0 - offset] = args[0]; + } args++; + + } + if(offset) { + args[0-offset] = '\0'; + offset = 0; + } } } argv = arga; @@ -265,7 +321,7 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED"); break; } - if((cbind->func->flags & CMDFLAG_CHECK_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) { + if(((cbind->func->flags & CMDFLAG_CHECK_AUTH) || (chan && chan != sent_chan && !isUserOnChan(user, chan))) && !(user->flags & USERFLAG_ISAUTHED)) { //check auth... struct command_check_user_cache *data = malloc(sizeof(*data)); char **temp_argv = malloc(argc*sizeof(*temp_argv)); @@ -300,18 +356,41 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u MYSQL_RES *res; MYSQL_ROW row; int uaccess; + char requested_uaccess = 0; int eventflags = (cbind->func->flags & (CMDFLAG_LOG | CMDFLAG_OPLOG)); if((cbind->func->flags & CMDFLAG_REQUIRE_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) { reply(tmp_text_client, user, "MODCMD_AUTH_REQUIRED"); return; } + if(chan && sent_chan != chan && !isUserOnChan(user, chan)) { + char user_in_chan = 0; + if((user->flags & USERFLAG_ISAUTHED)) { + //maybe there's another user authed to user->auth on the channel... + struct ChanUser *cchanuser; + for(cchanuser = getChannelUsers(chan, NULL); cchanuser; cchanuser = getChannelUsers(chan, cchanuser)) { + if((cchanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cchanuser->user->auth)) { + user_in_chan = 1; + break; + } + } + } + if(!user_in_chan) { + //check if we are allowed to execute commands in this channel + requested_uaccess = 1; + uaccess = getChannelAccess(user, chan); + if(!uaccess) { + reply(tmp_text_client, user, "MODCMD_CROSSCHAN", chan->name); + return; + } + } + } if(sent_chan && sent_chan != chan) { //check pubcmd of this channel 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); - if(row[0] && uaccess < atoi(row[0]) && !isGodMode(user)) { //NOTE: HARDCODED DEFAULT: pubcmd = 0 + int saccess = getChannelAccess(user, sent_chan); + if(row[0] && saccess < atoi(row[0]) && !isGodMode(user)) { //NOTE: HARDCODED DEFAULT: pubcmd = 0 reply(tmp_text_client, user, "MODCMD_PUBCMD", sent_chan->name); return; } @@ -370,7 +449,7 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u chan->flags |= CHANFLAG_CHAN_REGISTERED; chan->channel_id = atoi(row[0]); if((sent_chan && sent_chan == chan) || access_count || minaccess) { - uaccess = getChannelAccess(user, chan); + if(!requested_uaccess) uaccess = getChannelAccess(user, chan); if(uaccess < minaccess && isGodMode(user)) { eventflags |= CMDFLAG_OPLOG; } else if(uaccess < minaccess) { @@ -428,28 +507,31 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd); return; } - struct Event *event = createEvent(client, user, chan, cbind->func->name, argv, argc, eventflags); + struct Event *event = createEvent(client, user, chan, cbind, argv, argc, eventflags); cbind->func->func(client, user, chan, argv, argc, event); } static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) { - fd_set fds; + fd_set fds, fds2; char *trigger; struct ClientSocket *client; FD_ZERO(&fds); + FD_ZERO(&fds2); for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - 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(isUserOnChan(client->user, chan) && (client->flags & SOCKET_FLAG_PREFERRED) && ((client->botid == 0 && !FD_ISSET(client->clientid, &fds)) || (client->botid && !FD_ISSET(client->botid, &fds2)))) { + FD_SET(client->clientid, &fds); + FD_SET(client->botid, &fds2); + trigger = get_channel_trigger(client->botid, client->clientid, chan); if(trigger && stricmplen(message, trigger, strlen(trigger)) == 0) { handle_command(client, user, chan, message + strlen(trigger)); } } } for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(isUserOnChan(client->user, chan) && !FD_ISSET(client->botid, &fds)) { + if(isUserOnChan(client->user, chan) && ((client->botid == 0 && !FD_ISSET(client->clientid, &fds)) || (client->botid && !FD_ISSET(client->botid, &fds2)))) { FD_SET(client->botid, &fds); - trigger = get_channel_trigger(client->botid, chan); + FD_SET(client->botid, &fds2); + trigger = get_channel_trigger(client->botid, client->clientid, chan); if(trigger && stricmplen(message, trigger, strlen(trigger)) == 0) { handle_command(client, user, chan, message + strlen(trigger)); } @@ -484,7 +566,6 @@ int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, ch cmdfunc->paramcount = paramcount; cmdfunc->channel_access = channel_access; cmdfunc->global_access = global_access; - cmdfunc->triggered = 0; cmdfunc->next = cmd_functions; cmd_functions = cmdfunc; return 1; @@ -510,10 +591,10 @@ int set_trigger_callback(int botid, trigger_callback_t *func) { return 1; } -int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger) { +int changeBotwiseChannelTrigger(int botid, int clientid, struct ChanNode *chan, char *new_trigger) { struct trigger_cache *trigger; for(trigger = chan->trigger; trigger; trigger = trigger->next) { - if(trigger->botid == botid) { + if(trigger->botid == botid && (botid || trigger->clientid == clientid)) { free(trigger->trigger); trigger->trigger = strdup(new_trigger); return 1; @@ -522,11 +603,11 @@ int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger) { return 0; } -int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) { +int bind_botwise_cmd_to_function(int botid, int clientid, char *cmd, struct cmd_function *func) { int bind_index = get_binds_index(cmd[0]); struct cmd_binding *cbind; for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { - if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) + if(((botid && cbind->botid == botid) || (botid == 0 && clientid == cbind->clientid)) && strcmp(cbind->cmd, cmd) == 0) return 0; } cbind = malloc(sizeof(*cbind)); @@ -535,18 +616,20 @@ int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) { return 0; } cbind->botid = botid; + cbind->clientid = clientid; cbind->cmd = strdup(cmd); cbind->func = func; cbind->paramcount = 0; cbind->global_access = 0; cbind->channel_access = NULL; cbind->flags = 0; + cbind->triggered = 0; cbind->next = cmd_binds[bind_index]; cmd_binds[bind_index] = cbind; return 1; } -int bind_cmd_to_command(int botid, char *cmd, char *func) { +int bind_botwise_cmd_to_command(int botid, int clientid, char *cmd, char *func) { struct cmd_function *cmdfunc; int fbotid = botid; char *c; @@ -570,7 +653,7 @@ int bind_cmd_to_command(int botid, char *cmd, char *func) { int bind_index = get_binds_index(cmd[0]); struct cmd_binding *cbind; for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { - if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) + if(((botid && cbind->botid == botid) || (botid == 0 && clientid == cbind->clientid)) && strcmp(cbind->cmd, cmd) == 0) return 0; } cbind = malloc(sizeof(*cbind)); @@ -579,6 +662,7 @@ int bind_cmd_to_command(int botid, char *cmd, char *func) { return 0; } cbind->botid = botid; + cbind->clientid = clientid; cbind->cmd = strdup(cmd); cbind->func = cmdfunc; cbind->next = cmd_binds[bind_index]; @@ -586,15 +670,16 @@ int bind_cmd_to_command(int botid, char *cmd, char *func) { cbind->global_access = 0; cbind->channel_access = NULL; cbind->flags = 0; + cbind->triggered = 0; cmd_binds[bind_index] = cbind; return 1; } -int unbind_cmd(int botid, char *cmd) { +int unbind_botwise_cmd(int botid, int clientid, char *cmd) { int bind_index = get_binds_index(cmd[0]); struct cmd_binding *cbind, *last = NULL; for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) { - if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) { + if(cbind->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) { if(last) last->next = cbind->next; else @@ -644,6 +729,7 @@ void init_modcmd() { bind_chanmsg(got_chanmsg); bind_privmsg(got_privmsg); register_default_language_table(msgtab); + register_command(0, "linker", modcmd_linker, 0, 0, 0, 0); //fake command for subcommands } void free_modcmd() { @@ -686,11 +772,11 @@ void free_modcmd() { bot_aliases = NULL; } -void bind_set_parameters(int botid, char *cmd, char *parameters) { +void bind_botwise_set_parameters(int botid, int clientid, char *cmd, char *parameters) { int bind_index = get_binds_index(cmd[0]); 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->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) { if(cbind->paramcount) { int i; for(i = 0; i < cbind->paramcount; i++) @@ -709,11 +795,11 @@ void bind_set_parameters(int botid, char *cmd, char *parameters) { } } -void bind_set_global_access(int botid, char *cmd, int gaccess) { +void bind_botwise_set_global_access(int botid, int clientid, char *cmd, int gaccess) { int bind_index = get_binds_index(cmd[0]); 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->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) { if(gaccess > -1) { cbind->global_access = gaccess; cbind->flags |= CMDFLAG_OVERRIDE_GLOBAL_ACCESS; @@ -725,11 +811,11 @@ void bind_set_global_access(int botid, char *cmd, int gaccess) { } } -void bind_set_channel_access(int botid, char *cmd, char *chanaccess) { +void bind_botwise_set_channel_access(int botid, int clientid, char *cmd, char *chanaccess) { int bind_index = get_binds_index(cmd[0]); 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->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) { if(cbind->channel_access) free(cbind->channel_access); if(chanaccess) { @@ -744,18 +830,18 @@ void bind_set_channel_access(int botid, char *cmd, char *chanaccess) { } } -struct cmd_binding *find_cmd_binding(int botid, char *cmd) { +struct cmd_binding *find_botwise_cmd_binding(int botid, int clientid, char *cmd) { int bind_index = get_binds_index(cmd[0]); 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->botid == botid && (botid || clientid == cbind->clientid) && strcmp(cbind->cmd, cmd) == 0) { return cbind; } } return NULL; } -void bind_unbound_required_functions(int botid) { +void bind_botwise_unbound_required_functions(int botid, int clientid) { struct cmd_function *cmdfunc; int i, found; struct cmd_binding *cbind; @@ -764,7 +850,7 @@ void bind_unbound_required_functions(int botid) { found = 0; for(i = 0; i < 27; i++) { for(cbind = cmd_binds[i]; cbind; cbind = cbind->next) { - if(cbind->botid == botid && cbind->func == cmdfunc) { + if(cbind->botid == botid && (botid || clientid == cbind->clientid) && cbind->func == cmdfunc) { found = 1; break; } @@ -772,8 +858,8 @@ void bind_unbound_required_functions(int botid) { if(found) break; } - if(!found && bind_cmd_to_function(botid, cmdfunc->name, cmdfunc)) { - cbind = find_cmd_binding(botid, cmdfunc->name); + if(!found && bind_botwise_cmd_to_function(botid, clientid, cmdfunc->name, cmdfunc)) { + cbind = find_botwise_cmd_binding(botid, clientid, cmdfunc->name); cbind->flags |= CMDFLAG_TEMPONARY_BIND; } }