From f8689ed5c8d9d877f2b6063d98c28d942c346d44 Mon Sep 17 00:00:00 2001 From: pk910 Date: Thu, 25 Aug 2011 06:29:03 +0200 Subject: [PATCH] added cmd_op cmd_deop cmd_voice cmd_devoice cmd_opall cmd_deopall cmd_voiceall cmd_devoiceall --- DBHelper.c | 47 +++++++++++++++++++++++++++++++++++++++ DBHelper.h | 1 + UserNode.h | 2 ++ bot_NeonServ.c | 39 +++++++++++++++++++++++++------- cmd_neonserv_deop.c | 39 ++++++++++++++++++++++++++++++++ cmd_neonserv_deopall.c | 31 ++++++++++++++++++++++++++ cmd_neonserv_devoice.c | 35 +++++++++++++++++++++++++++++ cmd_neonserv_devoiceall.c | 31 ++++++++++++++++++++++++++ cmd_neonserv_op.c | 31 ++++++++++++++++++++++++++ cmd_neonserv_opall.c | 33 +++++++++++++++++++++++++++ cmd_neonserv_voice.c | 31 ++++++++++++++++++++++++++ cmd_neonserv_voiceall.c | 28 +++++++++++++++++++++++ 12 files changed, 340 insertions(+), 8 deletions(-) create mode 100644 cmd_neonserv_deop.c create mode 100644 cmd_neonserv_deopall.c create mode 100644 cmd_neonserv_devoice.c create mode 100644 cmd_neonserv_devoiceall.c create mode 100644 cmd_neonserv_op.c create mode 100644 cmd_neonserv_opall.c create mode 100644 cmd_neonserv_voice.c create mode 100644 cmd_neonserv_voiceall.c diff --git a/DBHelper.c b/DBHelper.c index 7d22a81..5871586 100644 --- a/DBHelper.c +++ b/DBHelper.c @@ -107,4 +107,51 @@ void _loadChannelSettings(struct ChanNode *chan) { chan->flags |= CHANFLAG_REQUESTED_CHANINFO; } +//TODO: fix performance: we should cache the user access +int isUserProtected(struct ChanNode *chan, struct UserNode *victim, struct UserNode *issuer) { + /* Don't protect if someone is attacking himself, or if the aggressor is an IRC Operator. */ + if(victim == issuer || (issuer->flags & USERFLAG_ISIRCOP)) return 0; + + /* Don't protect if no one is to be protected. */ + MYSQL_RES *res; + MYSQL_ROW row; + char protection; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0; + printf_mysql_query("SELECT `channel_protect` FROM `channels` WHERE `channel_id` = '%d'"); + res = mysql_use(); + if(!(row = mysql_fetch_row(res))) return 0; + if(row[0]) { + protection = (char) atoi(row[0]); + } else { + printf_mysql_query("SELECT `channel_protect` FROM `channels` WHERE `channel_name` = 'defaults'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + protection = (char) atoi(row[0]); + } + if(protection == 3) return 0; + + /* Don't protect if the victim isn't added to the channel, unless we are to protect non-users also. */ + int victim_access = getChannelAccess(victim, chan, 0); + if (!victim_access && protection != 0) return 0; + + /* Protect if the aggressor isn't a user because at this point, the aggressor can only be less than or equal to the victim. */ + int issuer_access = getChannelAccess(issuer, chan, 0); + if (!issuer_access) return 1; + + /* If the aggressor was a user, then the victim can't be helped. */ + if(!victim_access) return 0; + + switch(protection) { + case 0: + case 1: + if(victim_access >= issuer_access) return 1; + break; + case 2: + if(victim_access > issuer_access) return 1; + break; + } + return 0; +} + diff --git a/DBHelper.h b/DBHelper.h index 5c68b90..5c0c16d 100644 --- a/DBHelper.h +++ b/DBHelper.h @@ -17,5 +17,6 @@ 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) +int isUserProtected(struct ChanNode *chan, struct UserNode *victim, struct UserNode *issuer); #endif \ No newline at end of file diff --git a/UserNode.h b/UserNode.h index b475c75..6347ef5 100644 --- a/UserNode.h +++ b/UserNode.h @@ -29,6 +29,8 @@ struct UserNode { struct UserNode *next; }; +#define isNetworkService(USER) (USER->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)) + void init_UserNode(); void free_UserNode(); int is_valid_nick(const char *nick); diff --git a/bot_NeonServ.c b/bot_NeonServ.c index e74a890..a28c11f 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -33,6 +33,8 @@ static const struct default_language_entry msgtab[] = { {"NS_USER_OUTRANKED", "\002%s\002 outranks you (command has no effect)."}, {"NS_ACCESS_DENIED", "Access denied."}, {"NS_NO_ACCESS", "You lack sufficient access to use this command."}, + {"NS_USER_PROTECTED", "Sorry, \002%s\002 is protected."}, + {"NS_SERVICE_IMMUNE", "\002%s\002 may not be kicked, killed, banned, or deopped."}, {"NS_TABLE_NONE", " None"}, {"NS_INVALID_ACCESS_RANGE", "Invalid access range; minimum (%d) must be lower than maximum (%d)."}, {"NS_CLVL_DONE", "%s now has access \002%d\002 in %s."}, @@ -82,6 +84,19 @@ static const struct default_language_entry msgtab[] = { {"NS_GIVEOWNER_TIMEOUT", "You must wait %s before you can give ownership of \002%s\002 to someone else."}, {"NS_GIVEOWNER_CONFIRM", "To really give ownership to \002%1$s\002, you must use 'giveownership *%1$s %2$s'."}, {"NS_GIVEOWNER_DONE", "Ownership of \002%s\002 has been transferred to account \002%s\002."}, + {"NS_OP_FAIL", "\002%s\002 could not op some of the nicks you provided."}, + {"NS_OP_DONE", "Opped users in \002%s\002."}, + {"NS_VOICE_FAIL", "\002%s\002 could not voice some of the nicks you provided."}, + {"NS_VOICE_DONE", "Voiced users in \002%s\002."}, + {"NS_DEOP_FAIL", "\002%s\002 could not deop some of the nicks you provided."}, + {"NS_DEOP_DONE", "Deopped users in \002%s\002."}, + {"NS_DEVOICE_FAIL", "\002%s\002 could not devoice some of the nicks you provided."}, + {"NS_DEVOICE_DONE", "Devoiced users in \002%s\002."}, + {"NS_OPALL_SECURITY", "\002WARNING\002: Opping all users on a channel is very insecure! If you still want do op all users on %s use: '\002opall FORCE\002 [nick mask]'"}, + {"NS_OPALL_DONE", "Opped \002%d\002 users in %s."}, + {"NS_VOICEALL_DONE", "Voiced \002%d\002 users in %s."}, + {"NS_DEOPALL_DONE", "Deopped \002%d\002 users in %s."}, + {"NS_DEVOICEALL_DONE", "Devoiced \002%d\002 users in %s."}, {NULL, NULL} }; @@ -103,14 +118,14 @@ INCLUDE ALL CMD's HERE #include "cmd_neonserv_down.c" #include "cmd_neonserv_upall.c" #include "cmd_neonserv_downall.c" -//#include "cmd_neonserv_op.c" -//#include "cmd_neonserv_opall.c" -//#include "cmd_neonserv_deop.c" -//#include "cmd_neonserv_deopall.c" -//#include "cmd_neonserv_voice.c" -//#include "cmd_neonserv_voiceall.c" -//#include "cmd_neonserv_devoiceall.c" -//#include "cmd_neonserv_devoice.c" +#include "cmd_neonserv_op.c" +#include "cmd_neonserv_opall.c" +#include "cmd_neonserv_deop.c" +#include "cmd_neonserv_deopall.c" +#include "cmd_neonserv_voice.c" +#include "cmd_neonserv_voiceall.c" +#include "cmd_neonserv_devoice.c" +#include "cmd_neonserv_devoiceall.c" //#include "cmd_neonserv_uset.c" //#include "cmd_neonserv_kick.c" //#include "cmd_neonserv_kickban.c" @@ -247,6 +262,14 @@ void init_NeonServ() { register_command(BOTID, "mdeluser", neonserv_cmd_mdeluser, 2, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); register_command(BOTID, "trim", neonserv_cmd_trim, 2, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); register_command(BOTID, "giveowner", neonserv_cmd_giveowner, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + register_command(BOTID, "op", neonserv_cmd_op, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + register_command(BOTID, "deop", neonserv_cmd_deop, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + register_command(BOTID, "voice", neonserv_cmd_voice, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + register_command(BOTID, "devoice", neonserv_cmd_devoice, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + register_command(BOTID, "opall", neonserv_cmd_opall, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + register_command(BOTID, "deopall", neonserv_cmd_deopall, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + register_command(BOTID, "voiceall", neonserv_cmd_voiceall, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + register_command(BOTID, "devoiceall", neonserv_cmd_devoiceall, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); start_bots(); bind_bot_ready(neonserv_bot_ready); diff --git a/cmd_neonserv_deop.c b/cmd_neonserv_deop.c new file mode 100644 index 0000000..1261c37 --- /dev/null +++ b/cmd_neonserv_deop.c @@ -0,0 +1,39 @@ + +/* +* argv[0-*] nicks +*/ + +static CMD_BIND(neonserv_cmd_deop) { + int i, done_users; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(!checkChannelAccess(user, chan, "channel_canop", 1, 0)) { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + modeBuf = initModeBuffer(client, chan); + for(i = 0; i < argc; i++) { + cuser = searchUserByNick(argv[i]); + if(!cuser) continue; + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + if(isNetworkService(cuser)) { + reply(getTextBot(), user, "NS_SERVICE_IMMUNE", cuser->nick); + continue; + } + if(isUserProtected(chan, cuser, user)) { + reply(getTextBot(), user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + done_users++; + if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; + modeBufferDeop(modeBuf, argv[i]); + } + freeModeBuffer(modeBuf); + if(done_users == argc) + reply(getTextBot(), user, "NS_DEOP_DONE", chan->name); + else + reply(getTextBot(), user, "NS_DEOP_FAIL", client->user->nick); +} diff --git a/cmd_neonserv_deopall.c b/cmd_neonserv_deopall.c new file mode 100644 index 0000000..8e3c60c --- /dev/null +++ b/cmd_neonserv_deopall.c @@ -0,0 +1,31 @@ + +/* +* argv[0] (optional) nick mask +*/ + +static CMD_BIND(neonserv_cmd_deopall) { + int i, issuer_access, user_access, done_users; + char *nickmask = NULL; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(!checkChannelAccess(user, chan, "channel_canop", 1, 0)) { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + if(argc > 0) + nickmask = argv[0]; + modeBuf = initModeBuffer(client, chan); + issuer_access = getChannelAccess(user, chan, 0); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + victim_access = getChannelAccess(user, chan, 0); + if(victim_access >= issuer_access) continue; + if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; + modeBufferDeop(modeBuf, argv[i]); + done_users++; + } + freeModeBuffer(modeBuf); + reply(getTextBot(), user, "NS_DEOPALL_DONE", done_users, chan->name); +} diff --git a/cmd_neonserv_devoice.c b/cmd_neonserv_devoice.c new file mode 100644 index 0000000..7d079c7 --- /dev/null +++ b/cmd_neonserv_devoice.c @@ -0,0 +1,35 @@ + +/* +* argv[0-*] nicks +*/ + +static CMD_BIND(neonserv_cmd_devoice) { + int i, done_users; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(!checkChannelAccess(user, chan, "channel_canvoice", 1, 0)) { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + modeBuf = initModeBuffer(client, chan); + for(i = 0; i < argc; i++) { + cuser = searchUserByNick(argv[i]); + if(!cuser) continue; + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + if(isUserProtected(chan, cuser, user)) { + reply(getTextBot(), user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + done_users++; + if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue; + modeBufferDevoice(modeBuf, argv[i]); + } + freeModeBuffer(modeBuf); + if(done_users == argc) + reply(getTextBot(), user, "NS_DEVOICE_DONE", chan->name); + else + reply(getTextBot(), user, "NS_DEVOICE_FAIL", client->user->nick); +} diff --git a/cmd_neonserv_devoiceall.c b/cmd_neonserv_devoiceall.c new file mode 100644 index 0000000..409a0f4 --- /dev/null +++ b/cmd_neonserv_devoiceall.c @@ -0,0 +1,31 @@ + +/* +* argv[0] (optional) nick mask +*/ + +static CMD_BIND(neonserv_cmd_devoiceall) { + int i, issuer_access, user_access, done_users; + char *nickmask = NULL; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(!checkChannelAccess(user, chan, "channel_canvoice", 1, 0)) { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + if(argc > 0) + nickmask = argv[0]; + modeBuf = initModeBuffer(client, chan); + issuer_access = getChannelAccess(user, chan, 0); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + victim_access = getChannelAccess(user, chan, 0); + if(victim_access >= issuer_access) continue; + if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue; + modeBufferDevoice(modeBuf, argv[i]); + done_users++; + } + freeModeBuffer(modeBuf); + reply(getTextBot(), user, "NS_DEVOICEALL_DONE", done_users, chan->name); +} diff --git a/cmd_neonserv_op.c b/cmd_neonserv_op.c new file mode 100644 index 0000000..a780e87 --- /dev/null +++ b/cmd_neonserv_op.c @@ -0,0 +1,31 @@ + +/* +* argv[0-*] nicks +*/ + +static CMD_BIND(neonserv_cmd_op) { + int i, done_users; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(!checkChannelAccess(user, chan, "channel_canop", 1, 0)) { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + modeBuf = initModeBuffer(client, chan); + for(i = 0; i < argc; i++) { + cuser = searchUserByNick(argv[i]); + if(!cuser) continue; + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + done_users++; + if(chanuser->flags & CHANUSERFLAG_OPPED) continue; + modeBufferOp(modeBuf, argv[i]); + } + freeModeBuffer(modeBuf); + if(done_users == argc) + reply(getTextBot(), user, "NS_OP_DONE", chan->name); + else + reply(getTextBot(), user, "NS_OP_FAIL", client->user->nick); +} diff --git a/cmd_neonserv_opall.c b/cmd_neonserv_opall.c new file mode 100644 index 0000000..65195d2 --- /dev/null +++ b/cmd_neonserv_opall.c @@ -0,0 +1,33 @@ + +/* +* argv[0] "force" +* argv[1] (optional) nick mask +*/ + +static CMD_BIND(neonserv_cmd_opall) { + int i, done_users; + char *nickmask = NULL; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(!checkChannelAccess(user, chan, "channel_canop", 1, 0)) { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + if(!argc || strcmp(argv[0], "FORCE")) { + reply(getTextBot(), user, "NS_OPALL_SECURITY", chan->name); + return; + } + if(argc > 1) + nickmask = argv[1]; + modeBuf = initModeBuffer(client, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + if(chanuser->flags & CHANUSERFLAG_OPPED) continue; + modeBufferOp(modeBuf, argv[i]); + done_users++; + } + freeModeBuffer(modeBuf); + reply(getTextBot(), user, "NS_OPALL_DONE", done_users, chan->name); +} diff --git a/cmd_neonserv_voice.c b/cmd_neonserv_voice.c new file mode 100644 index 0000000..42d2a7a --- /dev/null +++ b/cmd_neonserv_voice.c @@ -0,0 +1,31 @@ + +/* +* argv[0-*] nicks +*/ + +static CMD_BIND(neonserv_cmd_voice) { + int i, done_users; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(!checkChannelAccess(user, chan, "channel_canvoice", 1, 0)) { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + modeBuf = initModeBuffer(client, chan); + for(i = 0; i < argc; i++) { + cuser = searchUserByNick(argv[i]); + if(!cuser) continue; + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + done_users++; + if(chanuser->flags & CHANUSERFLAG_VOICED) continue; + modeBufferVoice(modeBuf, argv[i]); + } + freeModeBuffer(modeBuf); + if(done_users == argc) + reply(getTextBot(), user, "NS_VOICE_DONE", chan->name); + else + reply(getTextBot(), user, "NS_VOICE_FAIL", client->user->nick); +} diff --git a/cmd_neonserv_voiceall.c b/cmd_neonserv_voiceall.c new file mode 100644 index 0000000..a2cf4f9 --- /dev/null +++ b/cmd_neonserv_voiceall.c @@ -0,0 +1,28 @@ + +/* +* argv[0] (optional) nick mask +*/ + +static CMD_BIND(neonserv_cmd_voiceall) { + int i, done_users; + char *nickmask = NULL; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(!checkChannelAccess(user, chan, "channel_canvoice", 1, 0)) { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + if(argc > 0) + nickmask = argv[0]; + modeBuf = initModeBuffer(client, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + if(chanuser->flags & CHANUSERFLAG_VOICED) continue; + modeBufferVoice(modeBuf, argv[i]); + done_users++; + } + freeModeBuffer(modeBuf); + reply(getTextBot(), user, "NS_VOICEALL_DONE", done_users, chan->name); +} -- 2.20.1