From: pk910 Date: Sat, 20 Aug 2011 06:12:23 +0000 (+0200) Subject: added cmd_clvl and moved all the database request functions to DBHelper.c X-Git-Tag: v5.3~516 X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=commitdiff_plain;h=e51f88d8e9882af0c3010ba1199d5935d1f99e50 added cmd_clvl and moved all the database request functions to DBHelper.c --- diff --git a/ChanNode.c b/ChanNode.c index 482c54c..14ab084 100644 --- a/ChanNode.c +++ b/ChanNode.c @@ -2,7 +2,6 @@ #include "ChanUser.h" #include "UserNode.h" #include "modcmd.h" -#include "mysqlConn.h" static struct ChanNode **chanList; static int modes_with_strarg, modes_with_intarg; @@ -375,19 +374,3 @@ void getModeString(struct ChanNode* chan, char *modesStr) { #undef MODE_VALUE #undef MODE_VALUE_INDEX } - - -void load_channel_settings(struct ChanNode *chan) { - if(!(chan->flags & CHANFLAG_REQUESTED_CHANINFO)) { - check_mysql(); - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", 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]); - } - chan->flags |= CHANFLAG_REQUESTED_CHANINFO; - } -} diff --git a/ChanNode.h b/ChanNode.h index 88cf2ac..c93625c 100644 --- a/ChanNode.h +++ b/ChanNode.h @@ -38,6 +38,4 @@ void* getModeValue(struct ChanNode* chan, char modeChar); void parseModes(struct ChanNode* chan, char *modeStr, char **argv, int argc); void getModeString(struct ChanNode* chan, char *modesStr); -void load_channel_settings(struct ChanNode *chan); - #endif \ No newline at end of file diff --git a/ChanUser.h b/ChanUser.h index c12de4a..d803ada 100644 --- a/ChanUser.h +++ b/ChanUser.h @@ -5,6 +5,10 @@ #define CHANUSERFLAG_VOICED 0x02 +#define DB_CHANUSER_SUSPENDED = 0x01 +#define DB_CHANUSER_AUTOINVITE = 0x02 +#define DB_CHANUSER_NOAUTOOP = 0x04 + #define CHANUSERFLAG_OPPED_OR_VOICED (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED) struct ChanNode; diff --git a/DBHelper.c b/DBHelper.c new file mode 100644 index 0000000..eb89536 --- /dev/null +++ b/DBHelper.c @@ -0,0 +1,98 @@ + +#include "DBHelper.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "mysqlConn.h" +#include "lang.h" + + +void _loadUserSettings(struct UserNode *user) { + check_mysql(); + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `user_lang`, `user_reply_privmsg`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + user->language = get_language_by_tag(row[0]); + if(user->language == NULL) user->language = get_default_language(); + if(strcmp(row[1], "0")) + user->flags |= USERFLAG_REPLY_PRIVMSG; + if(strcmp(row[2], "0")) + user->flags |= USERFLAG_GOD_MODE; + } else + user->language = get_default_language(); + user->flags |= USERFLAG_LOADED_SETTINGS; +} + +int isGodMode(struct UserNode *user) { + loadUserSettings(user); + return (user->flags & USERFLAG_GOD_MODE); +} + +int getChannelAccess(struct UserNode *user, struct ChanNode *chan, int override) { + if(!(user->flags & USERFLAG_ISAUTHED)) return 0; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0; + MYSQL_RES *res; + MYSQL_ROW row; + check_mysql(); + int caccess = 0; + printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + if(strcmp(row[2], "0") && override) + caccess = atoi(row[1]); + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%s' AND `chanuser_cid` = '%d'", row[0], chan->channel_id); + // + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + if(!(atoi(row[1]) & DB_CHANUSER_SUSPENDED) && atoi(row[0]) > caccess) + caccess = atoi(row[0]); + } + return caccess; + } + return 0; +} + +int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_override, int allow_501) { + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0; + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_setting, chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return 0; + int require_access = atoi(row[0]); + if(require_access == 0) return 1; + if(!(user->flags & USERFLAG_ISAUTHED)) return 0; + int caccess = 0; + printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%s' AND `chanuser_cid` = '%d'", row[0], chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + if(!(atoi(row[1]) & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row[0]); + } + } + if(caccess >= require_access) return 1; + if(caccess == 500 && require_access == 501 && allow_501) return 1; + return 0; +} + +void _loadChannelSettings(struct ChanNode *chan) { + check_mysql(); + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", 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]); + } + chan->flags |= CHANFLAG_REQUESTED_CHANINFO; +} + + diff --git a/DBHelper.h b/DBHelper.h new file mode 100644 index 0000000..a618541 --- /dev/null +++ b/DBHelper.h @@ -0,0 +1,14 @@ +#ifndef _DBHelper_h +#define _DBHelper_h + +#include "main.h" + +void _loadUserSettings(struct UserNode* user); +#define loadUserSettings(USER) if((USER->flags & USERFLAG_ISAUTHED) && !(USER->flags & USERFLAG_LOADED_SETTINGS)) _loadUserSettings(USER) +int isGodMode(struct UserNode *user); +int getChannelAccess(struct UserNode *user, struct ChanNode *chan, int override); +int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_override, int allow_501); +void _loadChannelSettings(struct ChanNode *chan); +#define loadChannelSettings(CHAN) if(!(CHAN->flags & CHANFLAG_REQUESTED_CHANINFO)) _loadChannelSettings(CHAN) + +#endif \ No newline at end of file diff --git a/Makefile b/Makefile index 6d4053e..8d40c2b 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ all: gcc -g -O2 ${LIBS} -c lang.c -o lang.o ${CFLAGS} gcc -g -O2 ${LIBS} -c HandleInfoHandler.c -o HandleInfoHandler.o ${CFLAGS} gcc -g -O2 ${LIBS} -c tools.c -o tools.o ${CFLAGS} + gcc -g -O2 ${LIBS} -c DBHelper.c -o DBHelper.o ${CFLAGS} gcc -g -O2 ${LIBS} -c bots.c -o bots.o ${CFLAGS} gcc -g -O2 ${LIBS} -c bot_NeonServ.c -o bot_NeonServ.o ${CFLAGS} diff --git a/UserNode.c b/UserNode.c index d85cceb..5b6c9c1 100644 --- a/UserNode.c +++ b/UserNode.c @@ -1,7 +1,5 @@ #include "UserNode.h" #include "ChanUser.h" -#include "mysqlConn.h" -#include "lang.h" static struct UserNode **userList; @@ -278,29 +276,3 @@ void clearTempUsers() { last_user = cuser; } } - - -void load_user_settings(struct UserNode *user) { - if(!(user->flags & USERFLAG_ISAUTHED) || (user->flags & USERFLAG_LOADED_SETTINGS)) - return; - check_mysql(); - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `user_lang`, `user_reply_privmsg`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - user->language = get_language_by_tag(row[0]); - if(user->language == NULL) user->language = get_default_language(); - if(strcmp(row[1], "0")) - user->flags |= USERFLAG_REPLY_PRIVMSG; - if(strcmp(row[2], "0")) - user->flags |= USERFLAG_GOD_MODE; - } else - user->language = get_default_language(); - user->flags |= USERFLAG_LOADED_SETTINGS; -} - -int isGodMode(struct UserNode *user) { - load_user_settings(user); - return (user->flags & USERFLAG_GOD_MODE); -} diff --git a/UserNode.h b/UserNode.h index 9a0c538..b475c75 100644 --- a/UserNode.h +++ b/UserNode.h @@ -42,7 +42,4 @@ int renameUser(struct UserNode* user, const char *new_nick); void delUser(struct UserNode* user, int freeUser); void clearTempUsers(); -void load_user_settings(struct UserNode* user); -int isGodMode(struct UserNode *user); - #endif diff --git a/bot_NeonServ.c b/bot_NeonServ.c index 5d4d977..8daa678 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -23,6 +23,10 @@ static const struct default_language_entry msgtab[] = { {"NS_ADDUSER_DONE", "Added %s to the %s user list with access %d."}, {"NS_NOT_ON_USERLIST", "%s lacks access to \002%s\002."}, {"NS_DELUSER_DONE", "Deleted %s (with access %d) from the %s user list."}, + {"NS_ACCESS_OUTRANKED", "You cannot give users access greater than or equal to your own."}, + {"NS_USER_OUTRANKED", "\002%s\002 outranks you (command has no effect)."}, + {"NS_ACCESS_DENIED", "Access denied."}, + {"NS_CLVL_DONE", "%s now has access \002%d\002 in %s."}, {NULL, NULL} }; diff --git a/cmd_neonserv_adduser.c b/cmd_neonserv_adduser.c index 6d1716e..f68f041 100644 --- a/cmd_neonserv_adduser.c +++ b/cmd_neonserv_adduser.c @@ -20,12 +20,16 @@ static CMD_BIND(neonserv_cmd_adduser) { MYSQL_RES *res; MYSQL_ROW row; check_mysql(); - //check acccess + checkChannelAccess(user, chan, "channel_canadd", 1, 0); caccess = atoi(argv[1]); if(caccess <= 0 || caccess > 500) { reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); return; } + if(caccess >= getChannelAccess(user, chan, 1)) { + reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); + return; + } //check own access if(argv[0][0] == '*') { //we've got an auth diff --git a/cmd_neonserv_clvl.c b/cmd_neonserv_clvl.c new file mode 100644 index 0000000..386a73b --- /dev/null +++ b/cmd_neonserv_clvl.c @@ -0,0 +1,101 @@ + +/* +* argv[0] - nick / *auth +* argv[1] - access +*/ +static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup); +static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, int caccess); + +struct neonserv_cmd_clvl_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + char *nick; + int access; +}; + +static CMD_BIND(neonserv_cmd_clvl) { + int caccess; + MYSQL_RES *res; + MYSQL_ROW row; + check_mysql(); + checkChannelAccess(user, chan, "channel_canclvl", 1, 0); + caccess = atoi(argv[1]); + if(caccess <= 0 || caccess > 500) { + reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); + return; + } + if(caccess >= getChannelAccess(user, chan, 1)) { + reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); + return; + } + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, argv[0], argv[0], caccess); + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, caccess); + } else { + struct neonserv_cmd_clvl_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->nick = strdup(argv[0]); + cache->access = caccess; + get_userauth(cuser, neonserv_cmd_clvl_nick_lookup, cache); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup) { + struct neonserv_cmd_clvl_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + neonserv_cmd_clvl_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, cache->access); + free(cache->nick); + free(cache); +} + +static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, int caccess) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row; + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is already added + printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + //clvl + if(atoi(row[0]) >= getChannelAccess(user, chan, 1)) { + reply(cache->textclient, cache->user, "NS_USER_OUTRANKED", nick); + return; + } + printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d' WHERE `chanuser_id` = '%s'", caccess, row[1]); + reply(textclient, user, "NS_CLVL_DONE", nick, caccess, chan->name); + return; + } + } + reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); +} diff --git a/cmd_neonserv_deluser.c b/cmd_neonserv_deluser.c index b98e7f3..acd2717 100644 --- a/cmd_neonserv_deluser.c +++ b/cmd_neonserv_deluser.c @@ -2,7 +2,6 @@ /* * argv[0] - nick / *auth */ -static AUTHLOOKUP_CALLBACK(neonserv_cmd_deluser_auth_lookup); static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup); static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth); @@ -18,28 +17,11 @@ static CMD_BIND(neonserv_cmd_deluser) { MYSQL_RES *res; MYSQL_ROW row; check_mysql(); + checkChannelAccess(user, chan, "channel_candel", 1, 0); if(argv[0][0] == '*') { //we've got an auth argv[0]++; - printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[0])); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, argv[0], row[0]); - } else { - //we need to create a new user... - //but first lookup the auth to check if it really exists - struct neonserv_cmd_deluser_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->nick = strdup(argv[0]); - lookup_authname(argv[0], neonserv_cmd_deluser_auth_lookup, cache); - } + neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, argv[0], argv[0]); } else { struct UserNode *cuser = getUserByNick(argv[0]); if(!cuser) { @@ -64,17 +46,6 @@ static CMD_BIND(neonserv_cmd_deluser) { } } -static AUTHLOOKUP_CALLBACK(neonserv_cmd_deluser_auth_lookup) { - struct neonserv_cmd_deluser_cache *cache = data; - if(!exists) { - //AUTH_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); - } else - neonserv_cmd_deluser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->nick, auth); - free(cache->nick); - free(cache); -} - static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup) { struct neonserv_cmd_deluser_cache *cache = data; if(!user) { @@ -104,6 +75,10 @@ static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct Clie printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); res = mysql_use(); if ((row = mysql_fetch_row(res)) != NULL) { + if(atoi(row[0]) >= getChannelAccess(user, chan, 1)) { + reply(textclient, cache->user, "NS_USER_OUTRANKED", nick); + return; + } //delete printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]); reply(textclient, user, "NS_DELUSER_DONE", nick, atoi(row[0]), chan->name); diff --git a/modcmd.c b/modcmd.c index 6079e3d..5c07fb4 100644 --- a/modcmd.c +++ b/modcmd.c @@ -9,6 +9,7 @@ #include "WHOHandler.h" #include "lang.h" #include "mysqlConn.h" +#include "DBHelper.h" struct trigger_callback { int botid; @@ -200,7 +201,7 @@ static void handle_command(struct ClientSocket *client, struct UserNode *user, s break; } if((cbind->func->flags & CMDFLAG_REGISTERED_CHAN)) { - load_channel_settings(chan); + loadChannelSettings(chan); if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED"); break;