X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=modcmd.c;h=5476d5e00a9798fff30610f4f01c2f5f70a4465c;hb=795115bf680185ae01043bd1222b78bfed8c1d87;hp=a84d5c8ed341c0d3469a0a41a250b97d602a9559;hpb=a50b4498f36c8ae8b26458ed93f6d9649b743cb6;p=NeonServV5.git diff --git a/modcmd.c b/modcmd.c index a84d5c8..5476d5e 100644 --- a/modcmd.c +++ b/modcmd.c @@ -1,11 +1,16 @@ #include "modcmd.h" #include "IRCEvents.h" +#include "IRCParser.h" #include "ClientSocket.h" #include "UserNode.h" #include "ChanNode.h" #include "ChanUser.h" #include "WHOHandler.h" +#include "lang.h" +#include "mysqlConn.h" +#include "DBHelper.h" +#include "EventLogger.h" struct trigger_callback { int botid; @@ -15,9 +20,9 @@ struct trigger_callback { }; struct command_check_user_cache { - struct ClientSocket *client; + struct ClientSocket *client, *textclient; struct UserNode *user; - struct ChanNode *chan; + struct ChanNode *chan, *sent_chan; char **argv; int argc; char *message; @@ -27,10 +32,22 @@ struct command_check_user_cache { static struct cmd_binding **cmd_binds; static struct cmd_function *cmd_functions = NULL; static struct trigger_callback *trigger_callbacks = NULL; +static struct ClientSocket *tmp_text_client; + +static const struct default_language_entry msgtab[] = { + {"MODCMD_LESS_PARAM_COUNT", "This command requires more parameters."}, + {"MODCMD_CHAN_REQUIRED", "You must provide the name of a channel that exists and the bot is on."}, + {"MODCMD_AUTH_REQUIRED", "You need to be authenticated with AuthServ to use this command."}, + {"MODCMD_CHAN_SUSPENDED", "This channel is currently suspended."}, + {"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."}, + {NULL, NULL} +}; static int get_binds_index(char first_char) { if(tolower(first_char) >= 'a' && tolower(first_char) <= 'z') { - return tolower(first_char - 'a'); + return tolower(first_char) - 'a'; } return 26; } @@ -72,21 +89,18 @@ static char* get_channel_trigger(int botid, struct ChanNode *chan) { return trigger->trigger; } +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); + static USERAUTH_CALLBACK(command_checked_auth) { struct command_check_user_cache *cache = data; - int execute_cmd = 1; - if((cache->cbind->func->flags & CMDFLAG_REQUIRE_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) { - //AUTH_REQUIRED - execute_cmd = 0; - } - if(execute_cmd) { - cache->cbind->func->func(cache->client, user, cache->chan, cache->argv, cache->argc); - } + 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); free(cache); } static void handle_command(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) { + struct ChanNode *sent_chan = chan; if(message[0] == '#') { char *chanName = message; message = strstr(message, " "); @@ -106,7 +120,9 @@ 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 && strcmp(cbind->cmd, message) == 0) { + if(cbind->botid == client->botid && stricmp(cbind->cmd, message) == 0) { + //get a text bot + tmp_text_client = get_prefered_bot(client->botid); //parse the arguments... char *arga[MAXNUMPARAMS]; char **argv; @@ -124,7 +140,7 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s } } argv = arga; - if(argc != 0 && argv[0][0] == '#') { + if(argc != 0 && argv[0][0] == '#' && !(cbind->func->flags & CMDFLAG_CHAN_PARAM)) { struct ChanNode *chan2 = getChanByName(argv[0]); if(chan2) { argv += 1; @@ -134,50 +150,56 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s } if(cbind->parameters) { //userdefined parameters... - char *uarga[MAXNUMPARAMS]; - char params[strlen(cbind->parameters)+1]; - strcpy(params, cbind->parameters); - int uargpos = 0, argi, allargs = 0; - char *ppos = params; - char *prev_ppos = params; - while((ppos = strstr(ppos, " "))) { - *ppos = '\0'; - if(prev_ppos[0] == '%') { - prev_ppos++; - if(prev_ppos[strlen(prev_ppos)-1] == '-') { + char *uargs[MAXNUMPARAMS]; + int uargc = 0; + char *a,*b = cbind->parameters; + int allargs, argi; + do { + a = strstr(b, " "); + if(a) *a = '\0'; + if(b[0] == '%') { + b++; + if(b[strlen(b)-1] == '-') { allargs = 1; - prev_ppos[strlen(prev_ppos)-1] = '\0'; - } else + b[strlen(b)-1] = '\0'; + argi = atoi(b); + b[strlen(b)-1] = '-'; + } else { allargs = 0; - argi = atoi(prev_ppos); + argi = atoi(b); + } if(argi > 0) { - if(argi <= argc) continue; - uarga[uargpos++] = argv[argi-1]; - if(allargs) { - for(;argi < argc; argi++) - uarga[uargpos++] = argv[argi-1]; + if(argi <= argc) { + uargs[uargc++] = argv[argi-1]; + if(allargs) { + for(argi++; argi <= argc; argi++) + uargs[uargc++] = argv[argi-1]; + } } - } else if(!strcmp(prev_ppos, "c")) - uarga[uargpos++] = (chan ? chan->name : NULL); - else if(!strcmp(prev_ppos, "n")) - uarga[uargpos++] = user->nick; + } else if(!strcmp(b, "c")) { + uargs[uargc++] = (chan ? chan->name : NULL); + } else if(!strcmp(b, "n")) { + uargs[uargc++] = user->nick; + } } else { - uarga[uargpos++] = prev_ppos; + uargs[uargc++] = b; } - ppos++; - prev_ppos = ppos; - } - argv = uarga; - argc = uargpos; + if(a) { + *a = ' '; + b = a+1; + } + } while(a); + argv = uargs; + argc = uargc; } if(argc < cbind->func->paramcount) { - //LESS_PARAM_COUNT + reply(tmp_text_client, user, "MODCMD_LESS_PARAM_COUNT"); break; } if((cbind->func->flags & CMDFLAG_REQUIRE_CHAN) && !chan) { - //CHAN_REQUIRED + reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED"); break; - } + } if((cbind->func->flags & CMDFLAG_CHECK_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) { //check auth... struct command_check_user_cache *data = malloc(sizeof(*data)); @@ -192,22 +214,156 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s data->client = client; data->user = user; data->chan = chan; + data->sent_chan = sent_chan; data->message = message; data->cbind = cbind; + data->textclient = tmp_text_client; get_userauth(user, command_checked_auth, data); return; - } - if((cbind->func->flags & CMDFLAG_REQUIRE_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) { - //AUTH_REQUIRED - break; - } - cbind->func->func(client, user, chan, argv, argc); + } else + handle_command_async(client, user, chan, sent_chan, cbind, argv, argc); break; } } free(message); } +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) { + MYSQL_RES *res; + MYSQL_ROW row; + int uaccess; + 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(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, 1); + if(row[0] && uaccess < atoi(row[0])) { //NOTE: HARDCODED DEFAULT: pubcmd = 0 + reply(tmp_text_client, user, "MODCMD_PUBCMD", sent_chan->name); + return; + } + } + } + int global_access = ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access); + if(global_access > 0) { + int user_global_access = 0; + printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + user_global_access = atoi(row[0]); + } + if(user_global_access < global_access) { + if(!user_global_access) + reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd); + else + reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED"); + return; + } + } + if((cbind->func->flags & CMDFLAG_REGISTERED_CHAN)) { + MYSQL_ROW defaults = NULL; + char access_list[256]; + int access_pos = 0; + int access_count = 0; + int minaccess = 0; + char *str_a, *str_b = cbind->func->channel_access, *str_c; + if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS) + str_b = cbind->channel_access; + access_list[0] = '\0'; + if(str_b) { + str_c = strdup(str_b); + str_b = str_c; + while((str_a = str_b)) { + str_b = strstr(str_a, ","); + if(str_b) { + *str_b = '\0'; + str_b++; + } + if(*str_a == '#') { + str_a++; + access_pos += sprintf(access_list+access_pos, ", `%s`", str_a); + access_count++; + } else { + if(atoi(str_a) > minaccess) + minaccess = atoi(str_a); + } + } + free(str_c); + } + if(!(chan->flags & CHANFLAG_REQUESTED_CHANINFO) || (sent_chan && sent_chan == chan) || access_count || minaccess) { + printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + 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); + if(uaccess < minaccess && isGodMode(user)) { + eventflags |= CMDFLAG_OPLOG; + } else if(uaccess < minaccess) { + //ACCESS DENIED + reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED"); + return; + } + if(!row[1] && !defaults) { + printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list); + defaults = mysql_fetch_row(mysql_use()); + } + if(sent_chan && (sent_chan == chan) && uaccess < (row[1] ? atoi(row[1]) : atoi(defaults[1]))) { + if(isGodMode(user)) { + eventflags |= CMDFLAG_OPLOG; + } else { + //PUBCMD + reply(tmp_text_client, user, "MODCMD_PUBCMD", chan->name); + return; + } + } + int i; + for(i = 0; i < access_count; i++) { + if(!row[2+i] && !defaults) { + printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list); + defaults = mysql_fetch_row(mysql_use()); + } + if(uaccess < (row[2+i] ? atoi(row[2+i]) : atoi(defaults[2+i]))) { + if(isGodMode(user)) { + eventflags |= CMDFLAG_OPLOG; + } else { + reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED"); + return; + } + } + } + } + } + chan->flags |= CHANFLAG_REQUESTED_CHANINFO; + } + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { + reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED"); + return; + } + printf_mysql_query("SELECT `botid`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED"); + return; + } else if(!strcmp(row[1], "1")) { + reply(tmp_text_client, user, "MODCMD_CHAN_SUSPENDED"); + return; + } + } + if((cbind->func->flags & CMDFLAG_REQUIRE_GOD) && !isGodMode(user)) { + reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd); + return; + } + struct Event *event = createEvent(client, user, chan, cbind->func->name, 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; char *trigger; @@ -242,7 +398,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, unsigned int flags) { +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) @@ -256,8 +412,10 @@ int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, un cmdfunc->botid = botid; cmdfunc->name = strdup(name); cmdfunc->func = func; - cmdfunc->flags = 0; + cmdfunc->flags = flags; cmdfunc->paramcount = paramcount; + cmdfunc->channel_access = channel_access; + cmdfunc->global_access = global_access; cmdfunc->next = cmd_functions; cmd_functions = cmdfunc; return 1; @@ -311,6 +469,8 @@ int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) { cbind->cmd = strdup(cmd); cbind->func = func; cbind->parameters = NULL; + cbind->global_access = 0; + cbind->channel_access = NULL; cbind->flags = 0; cbind->next = cmd_binds[bind_index]; cmd_binds[bind_index] = cbind; @@ -340,6 +500,8 @@ int bind_cmd_to_command(int botid, char *cmd, char *func) { cbind->func = cmdfunc; cbind->next = cmd_binds[bind_index]; cbind->parameters = NULL; + cbind->global_access = 0; + cbind->channel_access = NULL; cbind->flags = 0; cmd_binds[bind_index] = cbind; return 1; @@ -365,10 +527,24 @@ int unbind_cmd(int botid, char *cmd) { return 0; } +struct cmd_function *find_cmd_function(int botid, char *name) { + struct cmd_function *cmdfunc; + for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) { + if(cmdfunc->botid == botid && stricmp(cmdfunc->name, name) == 0) + break; + } + return cmdfunc; +} + +struct ClientSocket *getTextBot() { + return tmp_text_client; +} + void init_modcmd() { cmd_binds = calloc(27, sizeof(*cmd_binds)); bind_chanmsg(got_chanmsg); bind_privmsg(got_privmsg); + register_default_language_table(msgtab); } void free_modcmd() { @@ -380,6 +556,8 @@ void free_modcmd() { free(cbind->cmd); if(cbind->parameters) free(cbind->parameters); + if(cbind->channel_access) + free(cbind->channel_access); free(cbind); } } @@ -399,3 +577,62 @@ void free_modcmd() { trigger_callbacks = NULL; } +void bind_set_parameters(int botid, 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->parameters) + free(cbind->parameters); + cbind->parameters = strdup(parameters); + return; + } + } +} + +void bind_set_global_access(int botid, 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(gaccess > -1) { + cbind->global_access = gaccess; + cbind->flags |= CMDFLAG_OVERRIDE_GLOBAL_ACCESS; + } else { + cbind->flags &= ~CMDFLAG_OVERRIDE_GLOBAL_ACCESS; + } + return; + } + } +} + +void bind_set_channel_access(int botid, 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->channel_access) + free(cbind->channel_access); + if(chanaccess) { + cbind->channel_access = strdup(chanaccess); + cbind->flags |= CMDFLAG_OVERRIDE_CHANNEL_ACCESS; + } else { + cbind->channel_access = NULL; + cbind->flags &= ~CMDFLAG_OVERRIDE_CHANNEL_ACCESS; + } + return; + } + } +} + +struct cmd_binding *find_cmd_binding(int botid, 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) { + return cbind; + } + } + return NULL; +} +