]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/chanserv.c
LOC fix for non-ldap LOC where ldap is available
[irc/evilnet/x3.git] / src / chanserv.c
index 1363b683766a5701eac67c110b2d04b6ad9966a9..b3ecb6bc681b7cf89c415def1da62e445d3d2764 100644 (file)
@@ -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,
 #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"
 
 #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; n<nick->channels.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; n<user->channels.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; n<user->channels.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);