X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/5aa400d2612f104275d7f6b466a71f3139b4375b..18006b5cc4b0c4b72c638669a6ad5c8fb39ddf87:/src/chanserv.c diff --git a/src/chanserv.c b/src/chanserv.c index 1363b68..b3ecb6b 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -5,7 +5,7 @@ * * x3 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -21,9 +21,12 @@ #include "chanserv.h" #include "conf.h" #include "global.h" +#include "gline.h" +#include "ioset.h" #include "modcmd.h" #include "opserv.h" /* for opserv_bad_channel() */ #include "saxdb.h" +#include "shun.h" #include "spamserv.h" #include "timeq.h" @@ -111,6 +114,7 @@ #define KEY_NOTES "notes" #define KEY_TOPIC_MASK "topic_mask" #define KEY_OWNER_TRANSFER "owner_transfer" +#define KEY_MAXSETINFO "maxsetinfo" /* User data */ #define KEY_LEVEL "level" @@ -236,7 +240,7 @@ static const struct message_entry msgtab[] = { { "CSMSG_BAN_DONE", "Banned $b%s$b from %s." }, { "CSMSG_REASON_CHANGE", "Reason for LAMER $b%s$b changed." }, { "CSMSG_LAMER_EXTENDED", "Extended LAMER for $b%s$b, now expires in %s." }, - { "CSMSG_BAN_REMOVED", "Matching ban(s) and LAMER(s) in $b%s$b were removed." }, + { "CSMSG_BAN_REMOVED", "Ban(s) and LAMER(s) matching $b%s$b were removed." }, { "CSMSG_TRIMMED_LAMERS", "Trimmed $b%d LAMERs$b from the %s LAMER list that were inactive for at least %s." }, { "CSMSG_REDUNDANT_BAN", "$b%s$b is already banned in %s." }, { "CSMSG_REDUNDANT_LAMER", "$b%s$b is already LAMER'd in %s." }, @@ -299,6 +303,7 @@ static const struct message_entry msgtab[] = { { "CSMSG_SET_TOPICREFRESH", "$bTopicRefresh$b %d - %s" }, { "CSMSG_SET_RESYNC", "$bResync $b %d - %s" }, { "CSMSG_SET_BANTIMEOUT", "$bBanTimeout $b %d - %s" }, + { "CSMSG_SET_MAXSETINFO", "$bMaxSetInfo $b %d - maximum characters in a setinfo line." }, { "CSMSG_USET_AUTOOP", "$bAutoOp $b %s" }, { "CSMSG_USET_AUTOVOICE", "$bAutoVoice $b %s" }, @@ -518,6 +523,29 @@ static const struct message_entry msgtab[] = { { "CSMSG_DIE_ROLL", "A $b%lu$b shows on the %lu-sided die." }, { "CSMSG_HUGGLES_HIM", "\001ACTION huggles %s\001" }, { "CSMSG_HUGGLES_YOU", "\001ACTION huggles you\001" }, + { "CSMSG_ROULETTE_LOADS", "\001ACTION loads the gun and sets it on the table\001" }, + { "CSMSG_ROULETTE_NEW", "Please type .roulette to start a new round" } , + { "CSMSG_ROULETTE_BETTER_LUCK", "Better luck next time, %s" }, + { "CSMSG_ROULETTE_BANG", "Bang!!!" } , + { "CSMSG_ROULETTE_CLICK", "Click" } , + + { "CSMSG_SPIN_WHEEL1", "\001ACTION spins the wheel of misfortune for: %s\001" } , + { "CSMSG_SPIN_WHEEL2", "Round and round she goes, where she stops, nobody knows...!" } , + { "CSMSG_SPIN_WHEEL3", "The wheel of misfortune has stopped on..." } , + + { "CSMSG_SPIN_1", "1: Peer's gonna eat you!!!!" } , + { "CSMSG_SPIN_2", "2: Part all channels" } , + { "CSMSG_SPIN_3", "3: Part all channels" } , + { "CSMSG_SPIN_4", "4: /gline for random amount of time" } , + { "CSMSG_SPIN_5", "5: /shun for random amount of time" } , + { "CSMSG_SPIN_6", "6: Absolutely nothing" } , + { "CSMSG_SPIN_7", "7: Join a bunch of random channels, then /part all of 'em several times" } , + { "CSMSG_SPIN_8", "8: Abuse line added to /whois info" } , + { "CSMSG_SPIN_9", "9: /kick from each channel you're in" } , + { "CSMSG_SPIN_10", "10: Random Nick Change" } , + { "CSMSG_SPIN_11", "11: /kill" } , + { "CSMSG_SPIN_12", "12: Services ignore for random amount of time" } , + { "CSMSG_SPIN_13", "13: /kick and ban from each channel your're in" } , /* Other things */ { "CSMSG_EVENT_SEARCH_RESULTS", "$bChannel Events for %s$b" }, @@ -628,6 +656,9 @@ enum note_visible_type NOTE_VIS_PRIVILEGED }; +struct io_fd *socket_io_fd; +extern struct cManagerNode cManager; + struct note_type { enum note_access_type set_access_type; @@ -762,6 +793,28 @@ unsigned int chanserv_read_version = 0; /* db version control */ #define GetChannelAccess(channel, handle) _GetChannelUser(channel, handle, 0, 0) #define GetTrueChannelAccess(channel, handle) _GetChannelUser(channel, handle, 0, 1) +void sputsock(const char *text, ...) PRINTF_LIKE(1, 2); + +void +sputsock(const char *text, ...) +{ + va_list arg_list; + char buffer[MAXLEN]; + int pos; + + if (!cManager.uplink || cManager.uplink->state == DISCONNECTED) return; + buffer[0] = '\0'; + va_start(arg_list, text); + pos = vsnprintf(buffer, MAXLEN - 2, text, arg_list); + va_end(arg_list); + if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2; + buffer[pos] = 0; + log_replay(MAIN_LOG, true, buffer); + buffer[pos++] = '\n'; + buffer[pos] = 0; + ioset_write(socket_io_fd, buffer, pos); +} + unsigned short user_level_from_name(const char *name, unsigned short clamp_level) { @@ -2239,6 +2292,7 @@ static CHANSERV_FUNC(cmd_register) /* Initialize the channel's max user record. */ cData->max = channel->members.used; + cData->maxsetinfo = chanserv_conf.max_userinfo_length; if(handle != user->handle_info) reply("CSMSG_PROXY_SUCCESS", handle->handle, channel->name); @@ -2877,12 +2931,13 @@ static CHANSERV_FUNC(cmd_deluser) if(argc > 2) { access = user_level_from_name(argv[1], UL_OWNER); + char *useraccess = user_level_name_from_level(victim->access); if(!access) { reply("CSMSG_INVALID_ACCESS", argv[1]); return 0; } - if(access != victim->access) + if(strcasecmp(argv[1], useraccess)) { reply("CSMSG_INCORRECT_ACCESS", handle->handle, user_level_name_from_level(victim->access), argv[1]); return 0; @@ -6018,6 +6073,20 @@ static MODCMD_FUNC(chan_opt_usergreeting) return opt_greeting_common(user, cmd, argc, argv, "CSMSG_SET_USERGREETING", &channel->channel_info->user_greeting); } +static MODCMD_FUNC(chan_opt_maxsetinfo) +{ + unsigned int charmax; + + if(argc > 1) { + charmax = atoi(argv[1]); + if ((charmax > 0) && (charmax < chanserv_conf.max_userinfo_length)) + channel->channel_info->maxsetinfo = charmax; + } + + reply("CSMSG_SET_MAXSETINFO", channel->channel_info->maxsetinfo); + return 1; +} + static MODCMD_FUNC(chan_opt_modes) { struct mod_chanmode *new_modes; @@ -6528,9 +6597,9 @@ static MODCMD_FUNC(user_opt_info) { size_t bp; infoline = unsplit_string(argv + 1, argc - 1, NULL); - if(strlen(infoline) > chanserv_conf.max_userinfo_length) + if(strlen(infoline) > channel->channel_info->maxsetinfo) { - reply("CSMSG_INFOLINE_TOO_LONG", chanserv_conf.max_userinfo_length); + reply("CSMSG_INFOLINE_TOO_LONG", channel->channel_info->maxsetinfo); return 0; } bp = strcspn(infoline, "\001"); @@ -6704,8 +6773,8 @@ static CHANSERV_FUNC(cmd_giveownership) giveownership = calloc(1, sizeof(*giveownership)); giveownership->issued = now; - giveownership->old_owner = curr_user->handle->handle; - giveownership->target = new_owner_hi->handle; + giveownership->old_owner = strdup(curr_user->handle->handle); + giveownership->target = strdup(new_owner_hi->handle); giveownership->target_access = new_owner_old_access; if(override) { @@ -6934,6 +7003,239 @@ static CHANSERV_FUNC(cmd_wut) return 1; } +static CHANSERV_FUNC(cmd_roulette) +{ + if(channel) { + struct chanData *cData = channel->channel_info; + + if (cData) { + if (cData->roulette_chamber) { + DelUser(user, chanserv, 1, "BANG - Don't stuff bullets into a loaded gun"); + return 1; + } + + send_target_message(1, channel->name, cmd->parent->bot, "CSMSG_ROULETTE_LOADS"); + cData->roulette_chamber = 1 + rand() % 6; + } + } + + return 1; +} +static CHANSERV_FUNC(cmd_shoot) +{ + if(channel) { + struct chanData *cData = channel->channel_info; + + if (cData->roulette_chamber <= 0) { + reply("CSMSG_ROULETTE_NEW"); + return 1; + } + + cData->roulette_chamber--; + + if (cData->roulette_chamber == 0) { + reply("CSMSG_ROULETTE_BANG"); + reply("CSMSG_ROULETTE_BETTER_LUCK", user->nick); + DelUser(user, chanserv, 1, "BANG!!!!"); + } else + reply("CSMSG_ROULETTE_CLICK"); + } + + return 1; +} + +static void +chanserv_remove_abuse(void *data) +{ + struct userNode *remnick = data; + + DelUser(remnick, NULL, 1, ""); +} + +int lamepart(struct userNode *nick) { + struct modeNode *mn; + unsigned int count, n; + + for (n=count=0; nchannels.used; n++) { + mn = nick->channels.list[n]; + irc_svspart(chanserv, nick, mn->channel); + } + + return 0; +} + +static CHANSERV_FUNC(cmd_spin) +{ + if(!channel) + return 1; + + int type, lamep = 1; + char *tstr; + + tstr = conf_get_data("server/type", RECDB_QSTRING); + if(tstr) { + type = atoi(tstr); + if (type > 6) + lamep = 0; + } + + int wheel = 1 + rand() % 12; + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_WHEEL1", user->nick); + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_WHEEL2"); + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_WHEEL3"); + + if (wheel == 1) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_1"); + if (type < 7) + irc_kill(chanserv, user, "Connection reset by peer"); + else + sputsock("%s SQ %s :Connection reset by peer", self->numeric, user->numeric); + } + if (wheel == 2) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_2"); + if (lamep) + lamepart(user); + else + sputsock("%s SJ %s 0 "FMT_TIME_T, self->numeric, user->numeric, now); + } + if (wheel == 3) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_3"); + if (lamep) + lamepart(user); + else + sputsock("%s SJ %s 0 "FMT_TIME_T, self->numeric, user->numeric, now); + } + if (wheel == 4) { + char target[IRC_NTOP_MAX_SIZE + 3] = { '*', '@', '\0' }; + int wtime = 120 + rand() % 600; + + strcpy(target + 2, user->hostname); + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_4"); + + gline_add(chanserv->nick, target, wtime, "Reward for spinning the wheel of misfortune!", now, 1, 0); + irc_kill(chanserv, user, "Reward for spinning the wheel of misfortune!"); + } + if (wheel == 5) { + char target[IRC_NTOP_MAX_SIZE + 3] = { '*', '@', '\0' }; + int wtime = 120 + rand() % 600; + + strcpy(target + 2, user->hostname); + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_5"); + + shun_add(chanserv->nick, target, wtime, "Reward for spinning the wheel of misfortune!", now, 1); + } + if (wheel == 6) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_6"); + } + if (wheel == 7) { + int complete = 0; + int rndchans = 0; + int chango = 0; + int roundz0r = 0; + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_7"); + while(complete != 1) { + if (rndchans != 15) { + chango = 120 + rand() % 600; + sputsock("%s SJ %s #%d %ld", self->numeric, user->numeric, chango, now); + rndchans++; + } else { + if (roundz0r != 1) { + if (lamep) + lamepart(user); + else + sputsock("%s SJ %s 0 "FMT_TIME_T, self->numeric, user->numeric, now); + roundz0r = 1; + rndchans = 0; + } else { + if (lamep) + lamepart(user); + else + sputsock("%s SJ %s 0 "FMT_TIME_T, self->numeric, user->numeric, now); + complete = 1; + } + } + } + } + if (wheel == 8) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_8"); + irc_swhois(chanserv, user, "is being defecated on by services"); + } + if (wheel == 9) { + unsigned int count, n; + struct modeNode *mn; + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_9"); + + for (n=count=0; nchannels.used; n++) { + mn = user->channels.list[n]; + irc_kick(chanserv, user, mn->channel, "Reward for spinning the wheel of misfortune!"); + } + } + if (wheel == 10) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_10"); + + char *oldnick = NULL; + char *oldident = NULL; + char *oldhost = NULL; + char abusednick[NICKLEN] = ""; + int abusednum = time(NULL); + struct userNode *clone; + + oldnick = strdup(user->nick); + oldident = strdup(user->ident); + oldhost = strdup(user->hostname); + + snprintf(abusednick, NICKLEN, "Abused%d", abusednum+(1 + rand() % 120)); + while (1) { + log_module(MAIN_LOG, LOG_DEBUG, "Abused Nick: %s, Client Nick: %s", abusednick, user->nick); + snprintf(abusednick, NICKLEN, "Abused%d", abusednum+(1 + rand() % 120)); + if (user->nick != abusednick) + break; + } + + SVSNickChange(user, abusednick); + irc_svsnick(chanserv, user, abusednick); + + clone = AddClone(oldnick, oldident, oldhost, "I got abused by the wheel of misfortune :D"); + timeq_add(now + 300, chanserv_remove_abuse, clone); + } + if (wheel == 11) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_11"); + + irc_kill(chanserv, user, "Reward for spinning the wheel of misfortune!"); + } + if (wheel == 12) { + int gagged, ignoretime = 0; + char target[IRC_NTOP_MAX_SIZE + 13] = { '+', 'b', ' ', '*', '!', '*', '@', '\0' }; + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_12"); + + strcpy(target + 4, user->hostname); + srand(time(NULL)); + ignoretime = now + (1 + rand() % 120); + + gagged = gag_create(target, "wheelofabuse", "Reward for spinning the wheel of misfortune!", ignoretime); + } + if (wheel == 13) { + unsigned int count, n; + struct modeNode *mn; + char target[IRC_NTOP_MAX_SIZE + 1]; + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_13"); + + snprintf(target, sizeof(target), "+b *!*@%s", user->hostname); + for (n=count=0; nchannels.used; n++) { + mn = user->channels.list[n]; + irc_mode(chanserv, mn->channel, target); + irc_kick(chanserv, user, mn->channel, "Reward for spinning the wheel of misfortune!"); + } + } + + return 1; +} + #ifdef lame8ball static CHANSERV_FUNC(cmd_8ball) { @@ -7263,20 +7565,22 @@ handle_new_channel(struct chanNode *channel) int trace_check_bans(struct userNode *user, struct chanNode *chan) { - struct chanData *cData; struct banData *bData; + struct mod_chanmode *change; - if(!(cData = chan->channel_info)) - return 0; + change = find_matching_bans(&chan->banlist, user, NULL); + if (change) + return 1; - if(chan->banlist.used < MAXBANS) - { - for(bData = cData->bans; - bData && !user_matches_glob(user, bData->mask, MATCH_USENICK); - bData = bData->next); + /* lamer list */ + if (chan->channel_info) { + for(bData = chan->channel_info->bans; bData; bData = bData->next) { - if(bData) { - return 1; + if(!user_matches_glob(user, bData->mask, MATCH_USENICK)) + continue; + + if(bData) + return 1; } } @@ -7340,6 +7644,18 @@ check_bans(struct userNode *user, const char *channel) return 0; } +int +channel_user_is_exempt(struct userNode *user, struct chanNode *channel) +{ + unsigned int ii; + for(ii = 0; ii < channel->exemptlist.used; ii++) + { + if(user_matches_glob(user, channel->exemptlist.list[ii]->exempt, MATCH_USENICK)) + return true; + } + return false; +} + /* Welcome to my worst nightmare. Warning: Read (or modify) the code below at your own risk. */ @@ -7356,7 +7672,7 @@ handle_join(struct modeNode *mNode) unsigned int modes = 0, info = 0; char *greeting; - if(IsLocal(user) || !channel->channel_info || IsSuspended(channel->channel_info)) + if(IsLocal(user) || !channel || !channel->channel_info || IsSuspended(channel->channel_info)) return 0; cData = channel->channel_info; @@ -7404,7 +7720,7 @@ handle_join(struct modeNode *mNode) /* TODO: maybe only people above inviteme level? -Rubin */ /* We don't kick people with access */ - if(!uData) + if(!uData && !channel_user_is_exempt(user, channel)) { if(channel->banlist.used < MAXBANS) { @@ -8491,6 +8807,9 @@ chanserv_channel_read(const char *key, struct record_data *hir) str = database_get_data(channel, KEY_TOPIC, RECDB_QSTRING); cData->topic = str ? strdup(str) : NULL; + str = database_get_data(channel, KEY_MAXSETINFO, RECDB_QSTRING); + cData->maxsetinfo = str ? strtoul(str, NULL, 0) : chanserv_conf.max_userinfo_length; + if(!IsSuspended(cData) && (str = database_get_data(channel, KEY_MODES, RECDB_QSTRING)) && (argc = split_line(str, 0, ArrayLength(argv), argv)) @@ -8739,6 +9058,9 @@ chanserv_write_channel(struct saxdb_context *ctx, struct chanData *channel) } saxdb_end_record(ctx); + if (channel->maxsetinfo) + saxdb_write_int(ctx, KEY_MAXSETINFO, channel->maxsetinfo); + if(channel->modes.modes_set || channel->modes.modes_clear) { mod_chanmode_format(&channel->modes, buf); @@ -8886,6 +9208,7 @@ init_chanserv(const char *nick) { struct chanNode *chan; unsigned int i; + CS_LOG = log_register_type("ChanServ", "file:chanserv.log"); conf_register_reload(chanserv_conf_read); @@ -9021,6 +9344,9 @@ init_chanserv(const char *nick) DEFINE_COMMAND(huggle, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); DEFINE_COMMAND(calc, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); DEFINE_COMMAND(reply, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); + DEFINE_COMMAND(roulette, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); + DEFINE_COMMAND(shoot, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); + DEFINE_COMMAND(spin, 1, MODCMD_REQUIRE_AUTHED, "spin", "+nolog,+toy,+acceptchan", NULL); /* Channel options */ DEFINE_CHANNEL_OPTION(defaulttopic); @@ -9046,6 +9372,7 @@ init_chanserv(const char *nick) DEFINE_CHANNEL_OPTION(ctcpreaction); DEFINE_CHANNEL_OPTION(bantimeout); DEFINE_CHANNEL_OPTION(inviteme); + DEFINE_CHANNEL_OPTION(maxsetinfo); if(off_channel > 1) DEFINE_CHANNEL_OPTION(offchannel); modcmd_register(chanserv_module, "set defaults", chan_opt_defaults, 1, 0, "access", "owner", NULL);