X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fmodcmd.c;h=764ccedab1c7807c4e854a879c73157ca9434cc9;hb=689da1db7e2517c187ce76c6c553e20d630a7f36;hp=ce76ca056d52ada5f9e423dde6ab4708161bb141;hpb=382e8e7b3ee6d65c87ed795825cc3889fd915f3c;p=NeonServV5.git diff --git a/src/modcmd.c b/src/modcmd.c index ce76ca0..764cced 100644 --- a/src/modcmd.c +++ b/src/modcmd.c @@ -1,4 +1,4 @@ -/* modcmd.c - NeonServ v5.3 +/* modcmd.c - NeonServ v5.4 * Copyright (C) 2011-2012 Philipp Kreil (pk910) * * This program is free software: you can redistribute it and/or modify @@ -30,6 +30,7 @@ struct trigger_callback { int botid; + int module_id; trigger_callback_t *func; struct trigger_callback *next; @@ -128,7 +129,8 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u static USERAUTH_CALLBACK(command_checked_auth) { struct command_check_user_cache *cache = data; tmp_text_client = cache->textclient; - handle_command_async(cache->client, user, cache->chan, cache->sent_chan, cache->cbind, cache->argv, cache->argc); + if(user) + 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); @@ -141,6 +143,44 @@ static CMD_BIND(modcmd_linker) { //just empty } +static struct cmd_binding *modcmd_linker_command(struct ClientSocket *client, struct UserNode *user, struct cmd_binding *cbind, int bind_index, char **args_ptr) { + //links subcommands + char command[MAXLEN]; + struct cmd_binding *parent_bind = cbind; + char *args = *args_ptr; + 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; + } + *args_ptr = args; + if(cbind && cbind->func->func == modcmd_linker) { + return modcmd_linker_command(client, user, cbind, bind_index, args_ptr); + } + return cbind; + } 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) { + if(strstr(cbind->cmd + commandlen, " ")) continue; //ignore if there is another space in the command (sub-sub-command :D) + subcompos += sprintf(subcommands + subcompos, (subcompos ? ", %s" : "%s"), cbind->cmd + commandlen); + } + } + reply(tmp_text_client, user, "MODCMD_SUBCOMMANDS", parent_bind->cmd, (subcompos ? subcommands : "none")); + return NULL; + } +} + static void handle_command(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) { struct ChanNode *sent_chan = chan; if(message[0] == '#') { @@ -169,36 +209,8 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s //get a text bot tmp_text_client = get_botwise_prefered_bot(client->botid, (client->botid == 0 ? client->clientid : 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, (subcompos ? subcommands : "none")); - break; - } + cbind = modcmd_linker_command(client, user, cbind, bind_index, &args); + if(cbind == NULL) break; } if(statistics_enabled) statistics_commands++; @@ -242,14 +254,6 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s } } argv = arga; - if(argc != 0 && argv[0][0] == '#' && !(BIND_FLAGS(cbind) & CMDFLAG_CHAN_PARAM)) { - struct ChanNode *chan2 = getChanByName(argv[0]); - if(chan2) { - argv += 1; - argc -= 1; - chan = chan2; - } - } if(cbind->paramcount) { //userdefined parameters... args_buffer = malloc(MAXLEN * 2 * sizeof(*args_buffer)); @@ -330,6 +334,14 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s argv = uargs; argc = uargc; } + if(argc != 0 && argv[0][0] == '#' && !(BIND_FLAGS(cbind) & CMDFLAG_CHAN_PARAM)) { + struct ChanNode *chan2 = getChanByName(argv[0]); + if(chan2) { + argv += 1; + argc -= 1; + chan = chan2; + } + } if(argc < cbind->func->paramcount) { reply(tmp_text_client, user, "MODCMD_LESS_PARAM_COUNT"); break; @@ -357,7 +369,7 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s data->args_buffer = args_buffer; data->cbind = cbind; data->textclient = tmp_text_client; - get_userauth(user, command_checked_auth, data); + get_userauth(user, 0, command_checked_auth, data); return; } else handle_command_async(client, user, chan, sent_chan, cbind, argv, argc); @@ -381,7 +393,7 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u reply(tmp_text_client, user, "MODCMD_AUTH_REQUIRED"); return; } - if(chan && sent_chan != chan && !isUserOnChan(user, chan)) { + if(chan && sent_chan != chan && (BIND_FLAGS(cbind) & CMDFLAG_NO_CROSSCHAN) && !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... @@ -446,6 +458,7 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u str_b = cbind->channel_access; access_list[0] = '\0'; if(str_b) { + struct ChanUser *chanuser = getChanUser(user, chan); str_c = strdup(str_b); str_b = str_c; while((str_a = str_b)) { @@ -454,6 +467,15 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u *str_b = '\0'; str_b++; } + if(*str_a == '@' || *str_a == '+') { + //privs can override this access requirement + int priv = 0; + if(*str_a == '@') priv = CHANUSERFLAG_OPPED; + else if(*str_a == '%') priv = CHANUSERFLAG_HALFOPPED; + else if(*str_a == '+') priv = CHANUSERFLAG_VOICED; + if(chanuser && (chanuser->flags & priv)) continue; + str_a++; + } if(*str_a == '#') { str_a++; access_pos += sprintf(access_list+access_pos, ", `%s`", str_a); @@ -575,7 +597,7 @@ static void got_privmsg(struct UserNode *user, struct UserNode *target, char *me } } -int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags) { +int register_command(int botid, char *name, int module_id, 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 || cmdfunc->botid == 0) && strcmp(cmdfunc->name, name) == 0) @@ -588,6 +610,7 @@ int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, ch } cmdfunc->botid = botid; cmdfunc->name = strdup(name); + cmdfunc->module_id = module_id; cmdfunc->func = func; cmdfunc->flags = flags; cmdfunc->paramcount = paramcount; @@ -598,7 +621,7 @@ int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, ch return 1; } -int set_trigger_callback(int botid, trigger_callback_t *func) { +int set_trigger_callback(int botid, int module_id, trigger_callback_t *func) { static struct trigger_callback *cb = NULL; for(cb = trigger_callbacks; cb; cb = cb->next) { if(cb->botid == botid) @@ -614,6 +637,7 @@ int set_trigger_callback(int botid, trigger_callback_t *func) { cb->next = trigger_callbacks; trigger_callbacks = cb; } + cb->module_id = module_id; cb->func = func; return 1; } @@ -748,13 +772,13 @@ int unbind_botwise_cmd(int botid, int clientid, char *cmd) { return 0; } -int unbind_botwise_allcmd(int clientid) { +int unbind_botwise_allcmd(int botid, int clientid) { int i; for(i = 0; i < 27; i++) { struct cmd_binding *cbind, *next, *last = NULL; for(cbind = cmd_binds[i]; cbind; cbind = next) { next = cbind->next; - if(clientid == cbind->clientid) { + if((botid == 0 && clientid == cbind->clientid) || (botid && botid == cbind->botid)) { if(last) last->next = cbind->next; else @@ -803,10 +827,10 @@ struct ClientSocket *getTextBot() { void init_modcmd() { cmd_binds = calloc(27, sizeof(*cmd_binds)); - bind_chanmsg(got_chanmsg); - bind_privmsg(got_privmsg); + bind_chanmsg(got_chanmsg, 0); + bind_privmsg(got_privmsg, 0); register_default_language_table(msgtab); - register_command(0, "linker", modcmd_linker, 0, 0, 0, 0); //fake command for subcommands + register_command(0, "linker", 0, modcmd_linker, 0, 0, 0, 0); //fake command for subcommands } void free_modcmd() { @@ -990,3 +1014,54 @@ struct cmd_binding *getAllBinds(struct cmd_binding *last) { } while(bind_index < 27); return NULL; } + +void unregister_module_commands(int module_id) { + struct cmd_function *cmdfunct, *nextfunct, *prevfunct = NULL; + int i; + for(cmdfunct = cmd_functions; cmdfunct; cmdfunct = nextfunct) { + nextfunct = cmdfunct->next; + if(cmdfunct->module_id == module_id) { + for(i = 0; i < 27; i++) { + struct cmd_binding *cbind, *next, *last = NULL; + for(cbind = cmd_binds[i]; cbind; cbind = next) { + next = cbind->next; + if(cmdfunct == cbind->func) { + if(last) + last->next = cbind->next; + else + cmd_binds[i] = cbind->next; + free(cbind->cmd); + 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); + } else + last = cbind; + } + } + if(prevfunct) + prevfunct->next = nextfunct; + else + cmd_functions = nextfunct; + free(cmdfunct->name); + free(cmdfunct); + } else + prevfunct = cmdfunct; + } + struct trigger_callback *cb, *prevcb = NULL, *nextcb; + for(cb = trigger_callbacks; cb; cb = nextcb) { + nextcb = cb->next; + if(cb->module_id == module_id) { + if(prevcb) + prevcb->next = nextcb; + else + trigger_callbacks = nextcb; + free(cb); + } else + prevcb = cb; + } +}