]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/chanserv.c
Improved and committed the Life4Christ folks aut-oper patch.
[irc/evilnet/x3.git] / src / chanserv.c
index ec6aa80cf52561d0600a6bcf580b61bf7a111b57..9f6b80cdd8c15550d098628ffb6be65b25c38bb9 100644 (file)
@@ -38,6 +38,7 @@
 #define KEY_ADJUST_DELAY       "adjust_delay"
 #define KEY_CHAN_EXPIRE_FREQ   "chan_expire_freq"
 #define KEY_CHAN_EXPIRE_DELAY  "chan_expire_delay"
+#define KEY_BAN_TIMEOUT_FREQ    "ban_timeout_freq"
 #define KEY_MAX_CHAN_USERS             "max_chan_users"
 #define KEY_MAX_CHAN_BANS      "max_chan_bans"
 #define KEY_NICK               "nick"
@@ -288,18 +289,19 @@ static const struct message_entry msgtab[] = {
     { "CSMSG_SET_ENFTOPIC",      "$bEnfTopic    $b %d - and above can set the topic." },
     { "CSMSG_SET_PUBCMD",        "$bPubCmd      $b %d - and above can use public commands." },
     { "CSMSG_SET_SETTERS",       "$bSetters     $b %d - and above can change these settings." },
-/*    { "CSMSG_SET_CTCPUSERS",     "$bCTCPUsers   $b %d - and above can use ctcps." }, */
     { "CSMSG_SET_VOICE",         "$bvoice       $b %d - %s" },
     { "CSMSG_SET_PROTECT",       "$bProtect     $b %d - %s" },
     { "CSMSG_SET_TOYS",          "$bToys        $b %d - %s" },
     { "CSMSG_SET_CTCPREACTION",  "$bCTCPReaction$b %d - %s" },
     { "CSMSG_SET_TOPICREFRESH",  "$bTopicRefresh$b %d - %s" },
+    { "CSMSG_SET_BANTIMEOUT",    "$bBanTimeout  $b %d - %s" },
     { "CSMSG_USET_AUTOOP",       "$bAutoOp      $b %s" },
     { "CSMSG_USET_AUTOVOICE",    "$bAutoVoice   $b %s" },
     { "CSMSG_USET_AUTOINVITE",   "$bAutoInvite  $b %s" },
     { "CSMSG_USET_INFO",         "$bInfo        $b %s" },
 
     { "CSMSG_USER_PROTECTED", "Sorry, $b%s$b is protected." },
+    { "CSMSG_USER_PROTECTED_KICK", "That user is protected." }, /* No $ or %s replacements! */
     { "CSMSG_OPBY_LOCKED", "You may not op users who lack op or greater access." },
     { "CSMSG_HOPBY_LOCKED", "You may not halfop users who lack halfop or greater access." },
     { "CSMSG_PROCESS_FAILED", "$b$C$b could not process some of the nicks you provided." },
@@ -319,16 +321,25 @@ static const struct message_entry msgtab[] = {
     { "CSMSG_TOYS_DISABLED", "Toys are completely disabled." },
     { "CSMSG_TOYS_PRIVATE", "Toys will only reply privately." },
     { "CSMSG_TOYS_PUBLIC", "Toys will reply publicly." },
+
     { "CSMSG_TOPICREFRESH_NEVER", "Never refresh topic." },
     { "CSMSG_TOPICREFRESH_3_HOURS", "Refresh every 3 hours." },
     { "CSMSG_TOPICREFRESH_6_HOURS", "Refresh every 6 hours." },
     { "CSMSG_TOPICREFRESH_12_HOURS", "Refresh every 12 hours." },
     { "CSMSG_TOPICREFRESH_24_HOURS", "Refresh every 24 hours." },
+
     { "CSMSG_CTCPREACTION_NONE", "CTCPs are allowed" },
     { "CSMSG_CTCPREACTION_KICK", "Kick on disallowed CTCPs" },
     { "CSMSG_CTCPREACTION_KICKBAN", "Kickban on disallowed CTCPs" },
     { "CSMSG_CTCPREACTION_SHORTBAN",  "Short timed ban on disallowed CTCPs" },
     { "CSMSG_CTCPREACTION_LONGBAN", "Long timed ban on disallowed CTCPs" },
+    
+    { "CSMSG_BANTIMEOUT_NONE", "Bans will not be removed automatically."},
+    { "CSMSG_BANTIMEOUT_10M", "Bans will be removed after 10 minutes."},
+    { "CSMSG_BANTIMEOUT_2H", "Bans will be removed after 2 hours."},
+    { "CSMSG_BANTIMEOUT_4H", "Bans will be removed after 4 hours."},
+    { "CSMSG_BANTIMEOUT_1D", "Bans will be removed after 24 hours."},
+    { "CSMSG_BANTIMEOUT_1W", "Bans will be removed after 1 week."},
 
     { "CSMSG_INVITED_USER", "Invited $b%s$b to join %s." },
     { "CSMSG_INVITING_YOU_REASON", "$b%s$b invites you to join %s: %s" },
@@ -524,6 +535,7 @@ static struct
 
     unsigned long      db_backup_frequency;
     unsigned long      channel_expire_frequency;
+    unsigned long       ban_timeout_frequency;
 
     long               info_delay;
     unsigned int       adjust_delay;
@@ -670,6 +682,13 @@ struct charOptionValues {
     { 'b', "CSMSG_CTCPREACTION_KICKBAN" },
     { 't', "CSMSG_CTCPREACTION_SHORTBAN" },
     { 'T', "CSMSG_CTCPREACTION_LONGBAN" }
+}, banTimeoutValues[] = {
+    { '0', "CSMSG_BANTIMEOUT_NONE" },
+    { '1', "CSMSG_BANTIMEOUT_10M" },
+    { '2', "CSMSG_BANTIMEOUT_2H" },
+    { '3', "CSMSG_BANTIMEOUT_4H" },
+    { '4', "CSMSG_BANTIMEOUT_1D" },
+    { '5', "CSMSG_BANTIMEOUT_1W" }
 };
 
 static const struct {
@@ -684,7 +703,8 @@ static const struct {
     { "CSMSG_SET_PROTECT",      "protect",      'l', 0, ArrayLength(protectValues), protectValues },
     { "CSMSG_SET_TOYS",         "toys",         'p', 6, ArrayLength(toysValues), toysValues },
     { "CSMSG_SET_TOPICREFRESH", "topicrefresh", 'n', 8, ArrayLength(topicRefreshValues), topicRefreshValues },
-    { "CSMSG_SET_CTCPREACTION", "ctcpreaction", 'n', 10, ArrayLength(ctcpReactionValues), ctcpReactionValues }
+    { "CSMSG_SET_CTCPREACTION", "ctcpreaction", 'n', 10, ArrayLength(ctcpReactionValues), ctcpReactionValues },
+    { "CSMSG_SET_BANTIMEOUT",   "bantimeout", '0', 11, ArrayLength(banTimeoutValues), banTimeoutValues }
 };
 
 struct userData *helperList;
@@ -3390,6 +3410,68 @@ find_matching_bans(struct banList *bans, struct userNode *actee, const char *mas
     return change;
 }
 
+void expire_bans(UNUSED_ARG(void* data)) /* Real bans, not lamers */
+{
+    unsigned int jj, ii, count;
+    struct banNode *bn;
+    struct chanData *channel;
+    time_t bantimeout;
+    struct mod_chanmode *change;
+
+    log_module(CS_LOG, LOG_DEBUG, "Checking for expired bans");
+    /* Walk through every channel */
+    for(channel = channelList; channel; channel = channel->next) {
+        switch(channel->chOpts[chBanTimeout])
+        {
+            default: case '0': continue; /* Dont remove bans in this chan */
+            case '1': bantimeout = now - (10 * 60);          break; /* 10 minutes */
+            case '2': bantimeout = now - (2 * 60 * 60);      break; /* 2 hours */
+            case '3': bantimeout = now - (4 * 60 * 60);      break; /* 4 hours */
+            case '4': bantimeout = now - (24 * 60 * 60);     break; /* 24 hours */
+            case '5': bantimeout = now - (7 * 24 * 60 * 60); break; /* 1 week */
+        }
+        count = 0;
+        /* First find out how many bans were going to unset */
+        for (jj=0; jj < channel->channel->banlist.used; ++jj) {
+            if(channel->channel->banlist.list[jj]->set < bantimeout)
+                count++;
+        }
+        if(count > 0) {
+            /* At least one ban, so setup a removal */
+            change = mod_chanmode_alloc(count);
+            ii = 0;
+            /* Walk over every ban in this channel.. */
+            for (jj=0; jj < channel->channel->banlist.used; ++jj) {
+                bn = channel->channel->banlist.list[jj];
+                if (bn->set < bantimeout) {
+                    log_module(CS_LOG, LOG_DEBUG, "Removing ban %s from %s", bn->ban, channel->channel->name);
+
+                    /* Add this ban to the mode change */
+                    change->args[ii].mode = MODE_REMOVE | MODE_BAN;
+                    change->args[ii].u.hostmask = strdup(bn->ban);
+                    ii++;
+                    /* Pull this ban out of the list */
+                    banList_remove(&(channel->channel->banlist), bn);
+                    jj--;
+                    free(bn);
+                }
+            }
+            /* Send the modes to IRC */
+            mod_chanmode_announce(chanserv, channel->channel, change);
+
+            /* free memory from strdup above */
+            for(ii = 0; ii < count; ++ii)
+                free((char*)change->args[ii].u.hostmask);
+
+            mod_chanmode_free(change);
+        }
+    } 
+    /* Set this function to run again */
+    if(chanserv_conf.ban_timeout_frequency)
+        timeq_add(now + chanserv_conf.ban_timeout_frequency, expire_bans, NULL);
+}
+
+
 static int
 unban_user(struct userNode *user, struct chanNode *channel, unsigned int argc, char *argv[], struct svccmd *cmd, int action)
 {
@@ -5611,13 +5693,6 @@ static MODCMD_FUNC(chan_opt_setters)
     return channel_level_option(lvlSetters, CSFUNC_ARGS);
 }
 
-/*
-static MODCMD_FUNC(chan_opt_ctcpusers)
-{
-    return channel_level_option(lvlCTCPUsers, CSFUNC_ARGS);
-}
-*/
-
 static MODCMD_FUNC(chan_opt_userinfo)
 {
     return channel_level_option(lvlUserInfo, CSFUNC_ARGS);
@@ -5640,6 +5715,19 @@ static MODCMD_FUNC(chan_opt_inviteme)
     return channel_level_option(lvlInviteMe, CSFUNC_ARGS);
 }
 
+/* TODO:  Make look like this when no args are 
+ *        given:
+ *  -X3- -------------------------------
+ *  -X3- BanTimeout: Bans are removed: 
+ *  -X3- ----- * indicates current -----
+ *  -X3-   0: [*] Never.
+ *  -X3-   1: [ ] After 10 minutes.
+ *  -X3-   2: [ ] After 2 hours.
+ *  -X3-   3: [ ] After 4 hours.
+ *  -X3-   4: [ ] After 24 hours.
+ *  -X3-   5: [ ] After one week.
+ *  -X3- ------------- End -------------
+ */
 static int
 channel_multiple_option(enum charOption option, struct userNode *user, struct chanNode *channel, int argc, char *argv[], struct svccmd *cmd)
 {
@@ -5700,6 +5788,11 @@ static MODCMD_FUNC(chan_opt_ctcpreaction)
     return channel_multiple_option(chCTCPReaction, CSFUNC_ARGS);
 }
 
+static MODCMD_FUNC(chan_opt_bantimeout)
+{
+    return channel_multiple_option(chBanTimeout, CSFUNC_ARGS);
+}
+
 static MODCMD_FUNC(chan_opt_topicrefresh)
 {
     return channel_multiple_option(chTopicRefresh, CSFUNC_ARGS);
@@ -6293,7 +6386,7 @@ static CHANSERV_FUNC(cmd_8ball)
   static char eb[MAXLEN];
   unsigned int accum, i, j;
 
-  REQUIRE_PARAMS(1);
+  REQUIRE_PARAMS(2);
   accum = 0;
   for(i=1; i<argc; i++)
     for(j=0; argv[i][j]; j++)
@@ -6817,7 +6910,7 @@ handle_kick(struct userNode *kicker, struct userNode *victim, struct chanNode *c
 
     if(protect_user(victim, kicker, channel->channel_info))
     {
-        const char *reason = user_find_message(kicker, "CSMSG_USER_PROTECTED");
+        const char *reason = user_find_message(kicker, "CSMSG_USER_PROTECTED_KICK");
        KickChannelUser(kicker, channel, chanserv, reason);
     }
 
@@ -7086,6 +7179,8 @@ chanserv_conf_read(void)
     chanserv_conf.adjust_delay = str ? ParseInterval(str) : 30;
     str = database_get_data(conf_node, KEY_CHAN_EXPIRE_FREQ, RECDB_QSTRING);
     chanserv_conf.channel_expire_frequency = str ? ParseInterval(str) : 86400;
+    str = database_get_data(conf_node, KEY_BAN_TIMEOUT_FREQ, RECDB_QSTRING);
+    chanserv_conf.ban_timeout_frequency = str ? ParseInterval(str) : 600;
     str = database_get_data(conf_node, KEY_CHAN_EXPIRE_DELAY, RECDB_QSTRING);
     chanserv_conf.channel_expire_delay = str ? ParseInterval(str) : 86400*30;
     str = database_get_data(conf_node, KEY_NODELETE_LEVEL, RECDB_QSTRING);
@@ -7140,7 +7235,7 @@ chanserv_conf_read(void)
             /* multiple choice options */
             "CtcpReaction", "Protect", "Toys", "TopicRefresh",
             /* binary options */
-            "DynLimit", "NoDelete",
+            "DynLimit", "NoDelete", "BanTimeout",
             /* delimiter */
             NULL
         };
@@ -8019,8 +8114,8 @@ init_chanserv(const char *nick)
     DEFINE_CHANNEL_OPTION(toys);
     DEFINE_CHANNEL_OPTION(setters);
     DEFINE_CHANNEL_OPTION(topicrefresh);
-//    DEFINE_CHANNEL_OPTION(ctcpusers);
     DEFINE_CHANNEL_OPTION(ctcpreaction);
+    DEFINE_CHANNEL_OPTION(bantimeout);
     DEFINE_CHANNEL_OPTION(inviteme);
     if(off_channel > 1)
         DEFINE_CHANNEL_OPTION(offchannel);
@@ -8052,6 +8147,9 @@ init_chanserv(const char *nick)
     if(chanserv_conf.channel_expire_frequency)
        timeq_add(now + chanserv_conf.channel_expire_frequency, expire_channels, NULL);
 
+    if(chanserv_conf.ban_timeout_frequency)
+        timeq_add(now + chanserv_conf.ban_timeout_frequency, expire_bans, NULL);
+
     if(chanserv_conf.refresh_period)
     {
         time_t next_refresh;